Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Kohana]problem z zapytaniem
Forum PHP.pl > Forum > PHP > Frameworki
grzes999
Mam mały problem z zapytaniem. Załóżmy że mam dwie tabele, w jednej mam: id,obiekt a w drugiej inne_id i id_obiektu. Czyli tabele są połączone poprzez id obiektu. I teraz jeden obiekt może być kilka razy w drugiej.I teraz jak piszę:
  1. DB::select()->from('ogloszenie_wyp')->join('ogloszenie')->on('id_ogl', '=', 'id_ogloszenia')->execute();

to pobiera mi się tylko jedna wartość z drugiej tabeli a potrzebuję wszystkie. Proszę o pomoc.
thek
A składnię join() i from() w Kohanie tyś widział?
Wersja 2.x http://docs.kohanaphp.com/libraries/database/builder#join
Wersja 3.x http://kohanaframework.org/3.0/guide/datab...y/builder#joins
Teraz popatrz, porównaj ze swoim. Ja już nawet literówek nie wypominam bo dwie widzę od razu...
grzes999
Widziałem i ten przykład pisałem na szybko i pominąłem i ja nie mam problemu z tym że mi zapytanie nie dzial tylko z tym że pobiera tylko jeden rekord z drugiej tabeli.
r4xz
1. popraw temat
2. wklej w takim razie twoje zapytanie to może poznamy przyczynę takiego, a nie innego zachowania
thek
Grześ... W takim razie z czym masz problem? Z ubraniem zapytania w query buildera Kohany (przy okazji która wersja?) czy z samym skleceniem zapytania? Jeśli to pierwsze to jeszcze od biedy temat tu może zostać, ale jeśli to drugie to trochę niezbyt prawidłowy dział wybrałeś wink.gif
grzes999
Wersja Kohany 3.2 i zapytanie działa tylko z tej drugiej tabelipobiera mi tylko jeden rekord a nie wszystkie jakie są do danego id.

Moje zapytanie

  1. DB::select()->from('ogloszenie_wyp')->join('ogloszenie')->on('id_ogl', '=', 'id_ogloszenia')->execute();


Ewewntualnie może jakoś to rozbić na dwa zapytania tylko jak je póżniej połączyćquestionmark.gif
thek
Takie coś powinno wygenerować zapytanie:
SELECT tu_kolumny FROM ogloszenie_wyp JOIN ogloszenie ON ig_ogl = id_ogloszenia
Pytanie się rodzi czy o takie Ci chodzi? Czy wrzucone prosto do bazy daje Ci rzeczywiście to co chcesz? Bo może to nie jest problem z Kohaną, ale nieprawidłowo utworzonym zapytaniem? Zrób debug zapytania jakie generuje query builder (jest przechowywane w obiekcie) i porównaj z tym, jakie chcesz uzyskać. Możesz się zdziwić czasem wink.gif
skowron-line
@grzes999 najpierw napisz sobie zapytanie z palca, takie które zwraca żądany wynik w PMA, a później do QB wpisuj.
  1. echo DB::select()->from('ogloszenie_wyp')->join('ogloszenie')->on('id_ogl', '=', 'id_ogloszenia');

i wklej do PMA
thek
Nie echo smile.gif Query builder zwraca obiekt, więc nic to nie da. Poza tym kohana ma wbudowaną funkcję wyświetlającą, odpowiednik var_dump -> Kohana::debug($zmienne) http://kohanaframework.org/3.0/guide/kohana/debugging
skowron-line
Cytat(thek @ 28.03.2012, 07:30:02 ) *
Nie echo smile.gif Query builder zwraca obiekt, więc nic to nie da.

Zadziała też, wiem bo sam tak robię
z manuala
  1. echo Debug::vars((string) $query);
  2. // Should display:
  3. // SELECT `username`, `password` FROM `users` WHERE `username` = 'john'
grzes999
No i sprawdziłem i zapytanie jest takie jak chce i jeżeli wpisuje je ręcznie do bazy to otrzymuję to co chce. Może źle to wypisuje.

  1. foreach($oferty as $oferta) :
  2. echo $oferta['gdzie']; echo $oferta['od']; echo $oferta['do'];
  3. echo $oferta['opis'];
  4. echo $oferta['cena'];
  5. switch ($oferta['has_wyposazenie'])
  6. {
  7. case('1'):
  8. echo "lazienka";
  9. break;
  10. case('2'):
  11. echo "telewizor";
  12. break;
  13. case('3'):
  14. echo "radio";
  15. break;
  16. case('4'):
  17. echo "ognisko";
  18. break;
  19. case('5'):
  20. echo "gril";
  21. break;
  22. default:
  23. echo "Brak dodatowych opcji";
  24. break;
  25. }
  26.  
  27. endforeach;
skowron-line
A przypadkiem break w switch Ci nie kończy pętli foreach odrazu questionmark.gif

@down
odpowiedz w formie pytania
phpion
@up:
No co Ty smile.gif
grzes999
Cytat(skowron-line @ 28.03.2012, 12:17:39 ) *
A przypadkiem break w switch Ci nie kończy pętli foreach odrazu questionmark.gif

@down
odpowiedz w formie pytania


W takim razie w jaki sposób wykonać tylko te akcje, kótre chcę a nie wszystkie??
I jeszcze jedno pytanie bo teraz wyświetla mi kilka razy to samo.
To znaczy jeżeli do jednego obiektu jest kilka rekordów w drugiej tabeli to wyświetla tle razy ile jest rekordów w tej drugiej tabeli.
Można to jakoś ograniczyć. Wiem, że to jest bardziej pytanie z SQL ale nie będę już zakładał drugiego tematu.
skowron-line
Napisz co chcesz wyciągnąć z bazy, będzie prościej.
grzes999
W bazie mam w jednej tabeli mam hotele a w drugiej tabeli wyposażenie dodatkowe takie ognisko,gril,wifi,parking,itd i chcę wyciągnąć wszystkie informacje o pokoju. Z podstawowymi nie ma problemu tylko z tymi dodatkowymi się troszkę meczę.

hotel

id | gdzie | opis

wyposazenie

id_wyposazenia | co

has_wyposazenie

id_has | id_pokoju | id_wyposazenia

Mniej więcej tak wygląda moja baza i niestety musi tak zostać bo jest częścią większej całości i nie opłaca się już przerabiać.
thek
To w takim razie pchaj to jako tablicę, czyli where('pole', 'IN', TABLICA_Z_ID_WYPOSAŻENIA) smile.gif
U Ciebie nie jest bowiem JOINowanie problemem, ale kryterium wyszukiwawcze wink.gif
Twoje zapytanie więc to...
1. Jeśli jest podane w kryteriach wyposażenie dorób join na tabelę z wyposażeniem
2. Jeśli już zjoinowałes, dorzuć kryterium wyszukiwawcze, gdzie id_wyposażenia wybranego pchniesz jako tablicę do where('id_wyposazenia', 'in', $tablica_wybranych_id)
3. Dodatkowo pogrupuj to po id_pokoju lub id obiektu, zależnie co chcesz pokazać.
Tu następuje rozwidlenie bo mozna do sprawy podejść na 2 sposoby:
4.1. Nie muszą wystapić wszystkie kryteria wyszukiwawcze, ale musi być trafione choć jedno.
a. tylko order malejacy po zliczonej ilości różnych kryteriów (kilka pokoi w jednym obiekcie to kilka trafionych a ma być w takim wypadku zliczone jako 1 a nie kilka)
4.2. Muszą wystąpić wszystkie kryteria:
a. tu jest zabawa smile.gif Musisz policzyć ile masz kryteriów wyszukiwawczych dla każdego obiektu (znów uwaga jak w alternatywnym podejściu. Kilka trafień w to samo kryterium = 1, anie przypuśćmy 5) i wybrać te, gdzie liczba ta jest równa ilości kryteriów w zapytaniu. Having się kłania wink.gif

Jak rozwiązać kwestię wyposażenia? Prosto... Albo z cache, albo na początku skryptu pobierz/utwórz tablicę gdzie masz inna tablicę typu klucz_id => wyposażenie. Teraz z formularza pobierasz id wybranych elementów wyposażenia. Dla pewności sprawdź, czy Ci ktoś nie spreparował formularza i zrób częśc wspólną tego co przyszło z formularza oraz wzorcowych. array_intersect przy czym dla wygody można wszystkie klucze wzorcowe machnąć jako array_keys.

Jak sam widzisz, nie Kohana Ci sprawia problem, ale logika skryptu.
grzes999
thek dzięki za wyjaśnienie ale samo się trochę teraz zamotałem w tym co napisałeś ale na spokojnie powinienem to ogarnąć.

I może lepiej jest zrobić dwa zapytania?? To znaczy w modelu zrobił bym dwie funkcje. Jedna pobierała by wszystko i zwracała id_obiektu a druga by pobierała wszystkie atrybuty. Tylko nie wiem czy tak można :/

I tam jest małe niedopatrzenie w schemacie mojej bazy.

pokoju

id_pokoju | gdzie | opis

wyposazenie

id_wyposazenia | co

has_wyposazenie

id_has | id_pokoju | id_wyposazenia

Bo chyba rozważałeś, że id w tej pierwszej tabeli to co innego niż w tej ostatniej a to jest to samo.
thek
Metody modelu pisze się tak, by był przydatne wink.gif Co do tabeli to w ostatniej id_has nawet nie jest potrzebne. Wystarczy nadać klucz unique na połączone id_pokoju i id_wyposażenia. Co do reszty to join rób tylko gdy w searchu masz wybrane wyposażenie. Inaczej join jest zbędny.
grzes999
Próbuję pisać zapytanie tak jak mi poradziłeś thek ale mam problem z tablicą bo gdy ją deklaruję jako pustą to mi wywala błąd a gdy nie deklaruję to wiadomo błąd że nie jest zadeklarowana

Kod
Database_Exception [ 1064 ]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') GROUP BY `id_pokoju'`' at line 1 [ SELECT * FROM `pokoje` JOIN `has_wyposazenie` ON (`id_pokoju` = `id_pokl`) WHERE `id_wyposazenia` IN () GROUP BY `id_pokoju` ]


Moje zapytanie

  1. $result = DB::select()->from('pokoje)->join('has_wyposazenie')->on('id_pokoju', '=', 'id_pokl')
  2. ->where('id_wyposazenia', 'IN', $tablica)->group_by('id_pokoju')->execute();
skowron-line
Zobacz jakie zapytanie Ci wypluwa na ekran
  1. SELECT * FROM `pokoje` JOIN `has_wyposazenie` ON (`id_pokoju` = `id_pokl`) WHERE `id_wyposazenia` IN () GROUP BY `id_pokoju`

nie ma czegoś takiego jak IN (), między nawiasami coś musi się znajdować. Twoja zmienna jest pusta.
thek
Bo $tablica powinna zawierać pobrane z formularza id_wyposażenia. Nie może być pusta. Właśnie dlatego napisałem, że JOINujesz i dajesz to WHERE tylko gdy jakiekolwiek wyposażenie zostało wybrane. Query Builder istnieje, by sobie palnąć IF i wykryć czy mamy to zrobić "po drodze". Ja na Twoim miejscu przekazywałbym dane $_POST jako tablicę do metody szukającej. Metoda by ją sobie przefiltrowała i na podstawie danych uzupełniała odpowiednie warunki czy Joinowała odpowiednie tabele. Przykładowo bym w formularzu umieścił checkboxy jako tablicę (name="wyposazenie[]"), gdzie jako ich value podrzucałbym id_wyposażenia. Odczyt takiej tablicy, walnięcie części wspólnej z prawidłową tablicą id_wyposażenia (w ramach walidacji) i posłanie do warunku where() to wszystko co wystarczy zrobić.
grzes999
Tylko problem jest taki że ja nie mam formularza i nie wiem skąd ten pomysł ;p
Ja to pobieram z bazy i wyświetlam na stronie. Ogólnie większość treści jest pobierana z bazy wink.gif
Tylko z tym problemem nie mogę sobie poradzić.
thek
Jeśli to tylko pobór z bazy, to where niepotrzebne. Robisz group by i w select dajesz GROUP_CONCAT(wyposazenie_id), co Ci wszystkie id_wyposażenie dla pokoju walnie po przecinku.
grzes999
Dzięki wielkie wszystko działa Lkingsmiley.png

I jeszcze mam małe pytanie jeżeli chciał bym zrobić sobie funkcję, która będzie w switchu w zależności od id wstawiała obrazek.
To piszę sobie nową metodę w modelu coś takiego

  1. public function obrazki($id)
  2. {
  3. foreach ($id as $wyposazenie)
  4. {
  5. switch ($wyposazenie)
  6. {
  7. case('1'):
  8. echo "<p>lazienka</p>";
  9. break;
  10. case('2'):
  11. echo "<p>telewizor</p>";
  12. break;
  13. case('3'):
  14. echo "<p>radio</p>";
  15. break;
  16. case('4'):
  17. echo "<p>ognisko</p>";
  18. break;
  19. case('5'):
  20. echo "<p>gril</p>";
  21. break;
  22. default:
  23. echo "<p>Brak dodatowych opcji</p>";
  24. break;
  25. }
  26. }
  27. }


W kontrolerze piszę takie coś

  1. $oferta = Model::factory('gielda');
  2. $oferty = $oferta->oferta();
  3. $this->template->content->oferty = $oferty;
  4. $wyp=$oferta->obrazki($param);
  5. $this->template->content->wyp = $wyp;
  6.  


I w kontrolerze przy jej wywołaniu muszę wstawić parametr i teraz moje pytanie. Co wstawićquestionmark.gif
W widoku to wiadomo wstawiam id_wyposazenia i w pętli wyświetlam a co z kotrolerem??
W powyższym przypadku wyświetli wiadomy błąd.

  1. Undefined variable: param


thek
Jak dla mnie to źle podszedłeś do tego... Skoro funkcja wstawia obrazki, to ja to widze tak:
1. W kontrolerze do widoku wrzucasz jedynie tablicę z id_wyposażenia, albo string zawierający wszystkie id_wyposażenia oddzielone przecinkami lub innym delimiterem (czyli tak, jak dostajesz to z bazy)
2. Funkcja obrazki to Helper widoku, która odbiera ową tablicę lub string i w zależności od tego co to jest - reaguje.
a. jeśli to tablica to sprawdź ilość elementów i zwaliduj je pod kątem zgodności z bankiem id_wyposażenia. Jeśli po walidacji jest przynajmniej jeden element, puść na switch w pętli po elementach zwalidowanych, przy czym default ma być pusty.
b. jeśli to string to explode do tablicy i dalej już jak w punkcie a.
grzes999
Ok tylko że w zapytaniu oprócz id_wyposazenia pobieram też inne dane dotyczące pokoju.
I trochę głupie pytanie mógł byś podesłać jakiegoś linka jak zrobić takiego helpera.
Gdyż w Kohanie nie jestem tak bardzo obeznany.
Znalazłem takie coś tylko nie jestem pewien czy o to ci chodzi.

Kohana->helper
thek
Jeśli używasz Kohany z gałęzi 2.x to owszem, możesz tak zrobić. W Kohanie 3.x nieco inaczej, gdyż tam jest inna hierarchia w związku z HMVC, ale i tam można zrobić prosty myk, by działało jak helpery w Kohanie 2.x. Kwestia dodania jednego dodatkowego pliku extendującego "po drodze", jeśli ktoś się przyzwyczaił do używania helperów jak w 2.x
grzes999
Ja osobiście używam 3.2 tak że będę musiał coś w manualu poszukać.
Ale tak ogólnie to jak trzeba zapisać tą moją poprzednią funckję bez użycia helpera bo będę potrzebował wyświetlić do danego pokoju komentarze.
I wtedy tak by chyba było najprościej.
I jest jesze jeden problem tym razem chyba bardziej z Kohana.
Otóż w jednym zapytaniu pobieram wszystkie informacje o pokoju i do kazdego pokoju mogą być komentarze. Więc w drugim zapytaniu pobieram komentarze do tego pokoju. Wiem że mogę pobrać to w jednym zapytaniu ale te zapytania i tak są dość skomplikowane dlatego nie chce ich jeszcze bardziej komplikować. I teraz moje pytanie jak przekazać do drugiego zapytania id_obiektu pobrane z pierwszego. Moje dwa modele.

Do pobierania informacji o pokoju.

  1. public function oferta()
  2. {
  3. $result = DB::select('id_ogloszenia','gdzie','od','do','dodano','koniec','cena','opis',
  4. array('group_concat("has_wyposazenie")' , 'wyposazenie'))->from('ogloszenie')->join('ogloszenie_wyp')
  5. ->on('id_ogloszenia', '=', 'id_ogl')->group_by('id_ogloszenia')->execute();
  6. $result = $result->as_array();
  7. return $result;
  8. }


I drugi do pobierania komentarzy do pokoju i nie tylko

  1. public function ogloszenie()
  2. {
  3.  
  4. $result = DB::select('nazwa','oferta.cena','oferta.opis','obiekt.zdjecie','data_dodania',
  5. array('group_concat("wyposazenie_id")' , 'wyposazenie'))
  6. ->from('oferta')->join('ogloszenie')->on('oferta.id_ogloszenia','=','ogloszenie.id_ogloszenia')
  7. ->join('obiekt')->on('obiekt.id','=','id_obiektu')->join('user')->on('oferta.id_usera','=','user.id')
  8. ->join('obiekt_has_wyposazenie')->on('obiekt_id','=','obiekt.id')
  9. ->where('ogloszenie.id_ogloszenia','=',2)->group_by('nazwa')->order_by('oferta.cena')->execute();
  10. $result = $result->as_array();
  11. return $result;
  12. }


Jak widać na razie wstawiłem na stałe id_ogloszenia=2
Wiem że trzeba przekazać parametr w funkcji i wpisać go w zapytanie ale jak to później napisać w kontrolerze??
thek
A o parametrach funkcji słyszałeś? wink.gif
$model->ogłoszenie($zmienna);
Nie mów, że wszystkie funkcje do tej pory pisałeś i wywoływałeś bezparametrowo...
grzes999
No oczywiście że nie wink.gif tylko co ma być w kontrolerze w tej zmiennej??
Bo jak wrzucę nie zdefiniowaną to wiadomo błąd a jak wstawiłem pustą zmienną i w widoku tak wywyływałem

$wywolanie($ogloszenie['cos'])

To wywala mi błąd że call function must by string albo jakoś tak i głównie z tym mam problem.
thek
Napiszę tak... Przeczytaj jakiś poradnik o tym jak się tworzy i wywołuje klasy w Kohanie. Bez tego możemy Ci pomagać, pisać kod, a i tak nic nie zrozumiesz. Wpierw zapoznaj się z podstawami frameworka na jakichś tutorialach i wróć gdy już coś opanujesz. Skoro już się łapiesz za FW to wpierw go choć trochę poznaj byś wiedział co z czym ugryźć, a nie, że liznąłeś php i od razu się rzucasz na coś, czego idei nie rozumiesz. Czy jeśli nauczyłeś się jeździć na rowerze, to siadasz na motocykl bo "oba mają dwa koła, kierownicę i siedzenie oraz ramę"? Przeskoczyć z czystego php można od razu na framework, ale to wymaga zdolności już jakichś z innych języków i rozmienia zasad działania.
grzes999
Rozumiem mniej więcej zasadę działanie MVC. Mogę poczytać tutorial tylko cięzko znaleźć coś dobrego w sieci.
Niby czytałem manuala ale nie wile mi pomogło to przy moim problemie i dlatego proszę o przykład jak takie coś się piszę i wtedy łatwiej będzie mi wyciągnąć wnioski i zrozumieć.
Niby zrobiłem tylko nie wiem czy to jest poprawne w widoku wpisuje coś takiego i działa

  1. $ogloszenie = Model::factory('gielda')->ogloszenie($oferta['id_ogloszenia']);
thek
Bo tak właśnie wygląda jedno z możliwych poprawnych wywołań. Są krótsze także. Jeśli używałeś w modelu wywołania połączenia z bazą danych (DB) to chyba wiesz już jak wygląda krótsze wink.gif
grzes999
Dzięki wszystkim za bardzo dobrą i szybką pomoc.
Temat uważam za zamknięty wink.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.