Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Kohana] Pobranie z bazy tylko jednego wiersza, jednej komórki itp
Forum PHP.pl > Forum > PHP > Frameworki
lorak110786
Jako fan Peara i jego DB boli mnie że nie mogę (albo nie umiem) wyciągnąć tylko jednego wiersza za pomocą zapytania. Może najlepiej będzie na przykładzie. Załóżmy że chcę wyciągnąć sobie dane jakiegoś usera. W rezultacie spodziewam dostać tylko jeden wiersz. Robię w modelu (w uproszczeniu):

  1. public function getById($id) {
  2. return $this->db->query("SELECT * FROM users WHERE id_user = ?", $id)->result_array(false);
  3. }


Dostaję wtedy tablicę jednoelementową w której jest tablica z danymi usera, z której muszę wyłuskać ten jeden element. Czy jest jakiś sposób żeby dostać od razu tablicę z danymi usera? Dotychczas robiłem to używając array_pop():

  1. public function getById($id) {
  2. return array_pop($this->db->query("SELECT * FROM users WHERE id_user = ?", $id)->result_array(false));
  3. }


ale jest to rozwiązanie wg mnie nieeleganckie. Czy nie ma czegoś w stylu ->result_row()? Przekopałem dokumentację i pliki ale nic ciekawego nie było. Znalazłem coś takiego jak ->current() ale nie wiem czy to rozwiąże mój problem. Jak Wy sobie z tym radzicie?

Druga rzecz to przygotowywanie list do <selectów>. Mam tabelę userów, robimy zapytanie wyciągające id_user i login. Teraz chciałbym spreparować tak dane, żeby można je było wstawić do form::select. Muszę wszystko jeszcze raz przefeczować, wstawiając do indeksu tablicy id_user a do wartości jego login. W Pearze było to tak fajnie rozwiązane, że jeśli robiłem zapytanie "SELECT id_user, login FROM (...)" to id_user (w zasadzie pierwsza wybrana kolumna) mogła się od razu stać indeksem tablicy. Tu indeksy są z góry definiowane jako numeryczne. Czy można to jakoś zmienić? Jak Wy przygotowujecie tablicę z wartościami dla <selecta>?

Mowa o Kohana2.3.4, nie korzystam z ORM (na razie)
phpion
  1. public function getById($id) {
  2. $result = $this->db->query("SELECT * FROM users WHERE id_user = ?", $id)->result(FALSE);
  3.  
  4. if (count($result) == 1) {
  5. return $result->current();
  6. }
  7. else {
  8. return NULL;
  9. }
  10. }

Powinno zadziałać.
lorak110786
Pewnie zadziała, ale niezupełnie o to mi chodzi. Ten sam rezultat dostaję robiąc array_pop(), a zapisuję wszystko w jednej linijce. Właśnie chodzi mi o to, żeby się za bardzo nie rozwodzić. taki zamiennik result_array(false) zwracający tylko jeden wiersz. Chyba będę musiał coś takiego sobie sam dopisać...

A co z drugą częścią pytania?
piespluto
Cytat(lorak110786 @ 18.12.2010, 20:25:31 ) *
Pewnie zadziała, ale niezupełnie o to mi chodzi. Ten sam rezultat dostaję robiąc array_pop(), a zapisuję wszystko w jednej linijce.

  1. $result = $this->db->query("SELECT * FROM users WHERE id_user = ?", $id)->result(FALSE)->current();

krócej chyba się nie da smile.gif


thek
@Piespluto: Problem z Twoim kodem jest jeden... A co jeśli rekordu spełniającego warunek nie ma? Jak ma wyciągnąć current() z niczego? Ogólnie dobrze phpion już napisał i sam robię podobnie. Rozwiązaniem jest więc to, co sam autor zasugerował.

Co do wartości idących w select to nie liczę nigdy na indeksy i wartości z bazy. Często je jeszcze obrabiam i dlatego taka funkcjonalność jak "pierwsza kolumna staje się indeksem tablicy" jest m zazwyczaj zbędna. Poza tym skąd masz pewność, że wartość jest ZAWSZE unikatowa? Ja jako programista też jestem tylko człowiekiem i mogę się w zapytaniu walnąć. W efekcie dostanę wiersze mogące się duplikować (zakładam, że skrypt/funkcja tworzące select mogą dostać dowolną tablicę) a z tego co czytam, nie walidujesz tych danych, tylko zakładasz z góry ich unikatowość i możesz mieć potem problem.
Ormin
Nie latwiej posłużyć się ORMem i metodą find() ? : o
piespluto
Cytat(thek @ 18.12.2010, 23:29:44 ) *
A co jeśli rekordu spełniającego warunek nie ma? Jak ma wyciągnąć current() z niczego?

Wtedy zwróci NULL, wieć if else jest IMO zbędny.


thek
No właśnie nie do końca. Często mam do czynienia z sytuacjami, gdzie jako wynik mogę otrzymać 0 lub false (przykład to zapytanie zliczające - false to błąd zapytania, 0 to brak rekordów pasujących w wyniku, przy debugu to ogromna różnica) i muszę stosować operator porównania z uwzględnieniem typu, czyli === a w takim wypadku NULL robi problem smile.gif
lorak110786
Cytat(thek @ 18.12.2010, 23:29:44 ) *
Poza tym skąd masz pewność, że wartość jest ZAWSZE unikatowa? Ja jako programista też jestem tylko człowiekiem i mogę się w zapytaniu walnąć. W efekcie dostanę wiersze mogące się duplikować (zakładam, że skrypt/funkcja tworzące select mogą dostać dowolną tablicę) a z tego co czytam, nie walidujesz tych danych, tylko zakładasz z góry ich unikatowość i możesz mieć potem problem.


Wartość jest zawsze unikatowa, bo indeksami tablicy stają się wartości z kolumny z indeksem primary. To logiczne że nie wybieram na indeksy tablicy mającej się stać optionami, kolumny bez PRIMARY bądź UNIQUE. Jako programista porządnie testuję kod przed wpuszczeniem go w produkcję, więc jeśli się walnę w zapytaniu to od razu się skapnę, że np wybrałem 2 kolumny w dajmy na to odwrotnej kolejności, więc nie widzę problemu;)

Nigdzie też nie napisałem że nie waliduję danych. Robię to, jeśli jest potrzeba rzecz jasna, tylko że w kontrolerze. Z drugiej strony w sumie nie wiem co tu w tym konkretnym przypadku miałoby być do walidowania?

Cytat(thek @ 19.12.2010, 16:51:17 ) *
No właśnie nie do końca. Często mam do czynienia z sytuacjami, gdzie jako wynik mogę otrzymać 0 lub false (przykład to zapytanie zliczające - false to błąd zapytania, 0 to brak rekordów pasujących w wyniku, przy debugu to ogromna różnica) i muszę stosować operator porównania z uwzględnieniem typu, czyli === a w takim wypadku NULL robi problem smile.gif


A jaki problem robi null, bo nie widzę?

@piespluto
Można użyć faktycznie ->result()->current(). W zasadzie array_pop() działa tak samo, bo jeśli nie będzie wyników też da nulla. Tyle że array_pop() bierze ostatnią wartość z tablicy (gdyby było np kilka wierszy wyniku). Jakby co to array_shift() chyba wyciąga pierwszy element tablicy.

A co jeśli chcemy wyciągnąć tylko jedną komórkę z bazy w wstawić ją do zmiennej? Np. z zapytania "SELECT login FROM USERS WHERE id_user = 5"? Po current też dostanę tablicę więc musiałbym zrobić coś w stylu: return $res['login']; Tez jest to nieeleganckie tym bardziej że tu trzeba sprawdzić issetem czy w ogóle indeks 'login' istnieje. Można to zrobić używając znów array_pop() ale jest to też dość nieeleganckie. W PEAR było coś takiego jak ->getOne. Czy Kohana ma jakiś tego odpowiednik, albo czy zna ktoś jakiś rozszerzony moduł db? Zresztą w ogóle brakuje mi takich rzeczy jak właśnie getOne, getRow, getCol.
thek
A więc aby dorwać się do wierszy to current, ale możesz też przewijać się między rekordami używając next i previous itd -> http://docs.kohanaphp.com/libraries/database/result
Jeśli chcesz do kolumny wyniku to jeśli wiesz, że wynik jest, odnosisz się do nazwy kolumny, a więc choćby $this->db->query('bla, bla')->current()->nazwa_kolumny


@bottom: niestety nie spotkałem się z taką funkcjonalnością o jakiej piszesz. Chyba będziesz musiał ją zaimplementować sam, dziedzicząc po db i rozszerzając tę klasę o ową funkcję. No i w wymaganej klasie to ją ustawiać jako domyślny model połączenia z bazą smile.gif Na chwilę obecną nie widzę innego rozwiązania.
lorak110786
Cytat(thek @ 20.12.2010, 11:22:32 ) *
A więc aby dorwać się do wierszy to current, ale możesz też przewijać się między rekordami używając next i previous itd -> http://docs.kohanaphp.com/libraries/database/result
Jeśli chcesz do kolumny wyniku to jeśli wiesz, że wynik jest, odnosisz się do nazwy kolumny, a więc choćby $this->db->query('bla, bla')->current()->nazwa_kolumny

Dokumentację czytałem w pierwszej kolejności, więc wiem o tym:) Myślałem że jest jakiś sprytniejszy sposób nieopisany w dokumentacji (przeglądając pliki Kohany udało mi się już znaleźć kiedyś rzecz o której się nie mówi w dokumentacji a która jest użyteczna).

Co do kolumny, to nie zrozumiałeś mnie. Nie chcę wyciągnąć jednej wartości na podstawie kolumny, tylko całą kolumnę. Jeśli np. dam zapytanie "SELECT id_user, login FROM users" i użyję getCol to dostanę tablicę gdzie indeksami będą id_userów a wartościami loginy. W sam raz na wstawienie tego do <select> w widoku. W manualu peara ładnie to pokazano:
http://pear.php.net/manual/en/package.data...mmon.getcol.php
phpion
Cytat(lorak110786 @ 20.12.2010, 13:52:11 ) *
Jeśli np. dam zapytanie "SELECT id_user, login FROM users" i użyję getCol to dostanę tablicę gdzie indeksami będą id_userów a wartościami loginy. W sam raz na wstawienie tego do <select> w widoku.

ORM::select_list() Dopisanie tego do zwykłej klasy Database to przecież 2 minuty pracy.
lorak110786
Cytat(phpion @ 20.12.2010, 23:25:19 ) *
ORM::select_list() Dopisanie tego do zwykłej klasy Database to przecież 2 minuty pracy.


guitar.gif Dokładnie o to mi chodziło:) Czas zatem obadać w końcu tego ORMa.
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.