--=REKLAMA=--

Wyszukiwanie danych w JDatabase

Z Joomla!WikiPL

Wersja Zwiastun (dyskusja | edycje) z dnia 20:53, 7 gru 2013

(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)

Poradnik to połączenie dwóch niezależnych części:

  • Wstawianie, zmienianie i usuwanie danych z bazy danych.
  • Wyszukiwanie danych z jednej lub wielu tabel oraz przedstawianie ich w wielu formach

Ta sekcja dokumentu przedstawia sposoby wyszukiwania danych w bazie. Żeby zobaczyć inną część kliknij tutaj.

Wprowadzenie

Joomla wprowadza wyszukaną abstrakcyjną warstwę bazy danych, aby uprościć jej użycie. Nowe wersje Joomla Platform API wprowadza dodatkowe funkcje, które dodatkowo rozszerzają możliwości warstwy baz danych oraz wprowadzają funkcje takie jak połączenia (aby zwiększyć gamę serwerów baz danych oraz umożliwić tworzenie łańcuchów zapytań, aby zwiększyć czytelność kodu czy uprościć zapytania SQL).

Joomla może używać wielu rodzajów baz danych SQL oraz wprowadza różnorodność środowisk o różnych przedrostkach tabel. Dodatkiem jest to, że klasy automatycznie nawiązują połączenie z bazą danych. Oprócz obiektu potrzebujesz tylko dwóch linijek kodu, aby otrzymać wynik z bazy danych w wielu formatach. Używając abstrakcyjnej warstwy baz danych, zapewniamy maksymalną kompatybilność i elastyczność rozszerzenia.

Zapytania

Zapytania do baz danych zostały zmienione wraz z nową strukturą Joomla nazwaną "zapytania łańcuchowe". Jest to rekomendowany sposób tworzenia zapytań do bazy danych (chociaż "zapytania strunowwe" dalej są obsługiwane).

Zapytania łańcuchowe zakładają połączenie wielu metod, tak aby jedna wywoływana po drugiej powracała do obiektu, który może obsłużyć kolejną metodę, co zwiększa czytelność kodu.

Aby uzyskać nową instancję klasy JDatabaseQuery, możemy użyć metody getQuery klasy JDatabaseDriver:

$db = JFactory::getDbo();
 
$query = $db->getQuery(true);

JDatabaseDriver::getQuery przyjmuje jeden opcjonalny parametr ($new), który może przyjąć wartość prawda lub fałsz (domyślnie jest to fałsz).

Aby wykonać zapytanie, możemy posłużyć się metodami zawartymi w JDatabaseQuery (najczęściej) przy użyciu języka SQL, ukrywając tym samym składnię kwerendy uzależnioną w głównej mierze od programisty oraz zwiększając przenośność kodu źródłowego.

Niektóre z częściej używanych, dołączonych metod to: SELECT, FROM, JOIN, WHERE, ORDER. Są też metody takie jak INSERT, UPDATE, DELETE, które służą do modyfikacji rekordów w bazie danych. Dzięki nim i zapytaniom łańcuchowym metod, można stworzyć niemal każde zapytanie bez utraty przenośności kodu.

Wyszukiwanie danych z jednej tabeli

Poniżej znajduje się przykład tworzenia zapytania przy użyciu klasy JDatabaseQuery. Przy użyciu metod: select, from, where oraz order, można tworzyć zapytania elastyczne, łatwe w czytaniu oraz przenośne:

// tworzymy połączenie
$db = JFactory::getDbo();
 
// tworzymy obiekt odpowiedzialny za zapytania
$query = $db->getQuery(true);
 
// wyszukujemy wszystkie rekordy z tabeli "user profile", których klucz zaczyna się na "custom.".
// oraz porządkujemy wyniki rosnąco
$query->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')));
$query->from($db->quoteName('#__user_profiles'));
$query->where($db->quoteName('profile_key') . ' LIKE '. $db->quote('\'custom.%\''));
$query->order('ordering ASC');
 
// resetujemy zapytanie używając wcześniej wypełnionego obiektu zapytania
$db->setQuery($query);
 
// ładujemy wyniki jako listę obiektów klasy stdClass (zobacz więcej opcji przetwarzania wyników)
$results = $db->loadObjectList();

Zapytanie może być także wykonane poprzez tzw. zapytanie łańcuchowe:

$query
    ->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')))
    ->from($db->quoteName('#__user_profiles'))
    ->where($db->quoteName('profile_key') . ' LIKE '. $db->quote('\'custom.%\''))
    ->order('ordering ASC');

Zapytania łańcuchowe przydają się zwłaszcza przy bardziej skomplikowanych zapytaniach.

Wyszukiwanie rekordów z wielu tabel

Używając metody join klasy JDatabaseQuery, można wyszukać rekordy z wielu tabel. Funkcja join przyjmuje dwa argumenty: typ (inner, outer, left, right) i samo wyrażenie. W następnym przykładzie można zauważyć użycie wszystkich słów kluczowych. Będziemy ich też zwykle używać podczas pisania natywnych zapytań (czyli wykorzystując SQL), włączając w to słowo kluczowe AS (służy do tworzenia aliasów, czyli nazw odwołujących się do istniejących zasobów, np. kolumn) oraz ON (znajdującego zastosowanie w tworzeniu relacji między tabelami). Należy również zapamiętać, że aliasy tabel mogą być użyte do wszystkich metod (np. SELECT, WHERE, ORDER).

// tworzymy połączenie
$db = JFactory::getDbo();
 
// tworzymy obiekt odpowiedzialny za zapytania
$query = $db->getQuery(true);
 
// wyszukujemy wszystkie artykuły użytkowników, których nazwy zaczynają się na 'a'.
// porządkujemy je biorąc pod uwagę datę utworzenia
// uwaga: zamieszczając "a" jako drugi parametr posługujemy się aliasem, który wygeneruje '#__content' jako 'a'
 
$query
    ->select($db->quoteName(array('a.*', 'b.username', 'b.name')))
    ->from($db->quoteName('#__content', 'a'))
    ->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
    ->where($db->quoteName('b.username') . ' LIKE \'a%\'')
    ->order($db->quoteName('a.created') . ' DESC');
 
// resetujemy zapytanie używając wcześniej wypełnionego obiektu zapytania
$db->setQuery($query);
 
// ładujemy wyniki jako listę obiektów klasy stdClass (zobacz więcej opcji przetwarzania wyników)
$results = $db->loadObjectList();

Metoda join pozwala nam zapytać zarówno o tabelę content oraz tabelę user, pobierając artykuły z danymi autora. Istnieją także inne, poręczne metody jak: inner, left, right i outer join.

Możemy stworzyć zapytanie do więcej niż dwóch tabel jednocześnie:

$query
    ->select($db->quoteName(array('a.*', 'b.username', 'b.name', 'c.*', 'd.*')))
    ->from($db->quoteName('#__content', 'a'))
    ->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
    ->join('LEFT', $db->quoteName('#__user_profiles', 'c') . ' ON (' . $db->quoteName('b.id') . ' = ' . $db->quoteName('c.user_id') . ')')
    ->join('RIGHT', $db->quoteName('#__categories', 'd') . ' ON (' . $db->quoteName('a.catid') . ' = ' . $db->quoteName('d.id') . ')')
    ->where($db->quoteName('b.username') . ' LIKE \'a%\'')
    ->order($db->quoteName('a.created') . ' DESC');

Zauważ, jak tworzenie łańcucha zapytań pomaga w poprawie czytelności kodu dla dłuższych zapytań.

Wyniki zapytań

Klasa bazy danych zawiera wiele metod pracy z wynikami pracy kwerend.

Pojedyncza wartość

loadResult()

Użyj loadResult() jeśli spodziewasz się pojedynczej wartości jako wynik pracy kwerendy.

id imię i nazwisko email nazwa użytkownika
1 John Smith johnsmith@domain.example johnsmith
2 Magda Hellman magda_h@domain.example magdah
3 Yvonne de Gaulle ydg@domain.example ydegaulle

Najczęściej znajduje to zastosowanie w pobieraniu ilości zwróconych rekordów:

$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('COUNT(*)');
$query->from($db->quoteName'#__my_table');
$query->where($db->quoteName('name')." = ".$db->quote($value));
 
// resetujemy zapytanie używając wcześniej wypełnionego obiektu zapytania
$db->setQuery($query);
$count = $db->loadResult();

albo zależy nam na wyszukaniu pojedynczego pola jako wiersz tabeli (ewentualnie pojedyncze pole z wiersza)

$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('field_name');
$query->from($db->quoteName('#__my_table'));
$query->where($db->quoteName('some_name')." = ".$db->quote($some_value));
 
$db->setQuery($query);
$result = $db->loadResult();

Pojedynczy wiersz

Każda z tych funkcji zwraca wynik jako pojedynczny rekord z basy danych, chociaż poprzez wywołanie tej metody kilka razy można uzyskać już kilka (o ile spełniają odpowiednie kryteria).

id imię i nazwisko email nazwa użytkownika
1 John Smith johnsmith@domain.example johnsmith
2 Magda Hellman magda_h@domain.example magdah
3 Yvonne de Gaulle ydg@domain.example ydegaulle

loadRow()

loadRow() zwraca tablicę numeryczną jako pojedynczy wiersz w tabeli:

. . .
$db->setQuery($query);
$row = $db->loadRow();
print_r($row);

otrzymamy:

Array ( [0] => 1 [1] => John Smith [2] => johnsmith@domain.example [3] => johnsmith ) 
Aby uzykać dostęp do pojedynczych wartości można posłużyć się:
$row['index'], gdzie index to numer określający kolumnę np.: $row['2']

Uwagi:

  1. Indeksy w tablicy zaczynają się od zera..
  2. Użycie tej funkcji do pobrania kilku, dalszych wierszy może być bardzo użyteczne.

loadAssoc()

loadAssoc() zwraca tablicę asocjacyjną jako pojedynczy rekord tabeli:

. . .
$db->setQuery($query);
$row = $db->loadAssoc();
print_r($row);

otrzymamy:

Array ( [id] => 1 [name] => John Smith [email] => johnsmith@domain.example [username] => johnsmith )
Aby uzykać dostęp do pojedynczych wartości można posłużyć się:
$row['name'], gdzie name to numer określający kolumnę np.: $row['username']

Uwagi:

  1. Użycie tej funkcji do pobrania kilku, dalszych wierszy może być bardzo użyteczne.

loadObject()

loadObject zwraca obiekt jako pojedynczy rekord z tabeli:

. . .
$db->setQuery($query);
$result = $db->loadObject();
print_r($result);

otrzymamy:

stdClass Object ( [id] => 1 [name] => John Smith [email] => johnsmith@domain.example [username] => johnsmith )
Aby uzykać dostęp do pojedynczych wartości można posłużyć się:
$row->index, gdzie index to numer określający kolumnę np.: $row->email

Uwagi:

  1. Użycie tej funkcji do pobrania kilku, dalszych wierszy może być bardzo użyteczne.

Pojedyncza kolumna

Każda z poniższych funkcji ma za zadanie zwrócić pojedynczą kolumnę tabeli.

id imię i nazwisko email nazwa użytkownika
1 John Smith johnsmith@domain.example johnsmith
2 Magda Hellman magda_h@domain.example magdah
3 Yvonne de Gaulle ydg@domain.example ydegaulle

loadColumn()

loadColumn() zwraca tablicę numeryczną jako pojedynczą kolumnę tabeli:

$query->select('name'));
      ->from . . .";
. . .
$db->setQuery($query);
$column= $db->loadColumn();
print_r($column);

otrzymamy:

Array ( [0] => John Smith [1] => Magda Hellman [2] => Yvonne de Gaulle )
Aby uzyskać dostęp do danych, można posłużyć się:
$column['index'], gdzie index to numer określający kolumnę np.: $row['1']

Uwagi:

  1. Indeksy w tablicy zaczynają się od zera..
  2. loadColumn() jest równoznaczne z loadColumn(0)

loadColumn($index)

loadColumn($index) zwraca tablicę numeryczną jako pojedynczą kolumnę tabeli:

$query->select(array('name', 'email', 'username'));
      ->from . . .";
. . .
$db->setQuery($query);
$column= $db->loadColumn(1);
print_r($column);

otrzymamy:

Array ( [0] => johnsmith@domain.example [1] => magda_h@domain.example [2] => ydg@domain.example )
Aby uzyskać dostęp do danych, można posłużyć się:
$column['index'], gdzie index to numer określający kolumnę np.: $row['2']

loadColumn($index) pozwala na iterowanie kolejnych wyników zapytań

. . .
$db->setQuery($query);
for ( $i = 0; $i <= 2; $i++ ) {
  $column= $db->loadColumn($i);
  print_r($column);
}

otrzymamy:

Array ( [0] => John Smith [1] => Magda Hellman [2] => Yvonne de Gaulle )
Array ( [0] => johnsmith@domain.example [1] => magda_h@domain.example [2] => ydg@domain.example )
Array ( [0] => johnsmith [1] => magdah [2] => ydegaulle )

</pre>

Uwagi:

  1. Indeksy w tablicy zaczynają się od zera.

Wiele rekordów

Każda z tych funkcji zwraca wiele rekordów jednocześnie.

id imię i nazwisko email nazwa użytkownika
1 John Smith johnsmith@domain.example johnsmith
2 Magda Hellman magda_h@domain.example magdah
3 Yvonne de Gaulle ydg@domain.example ydegaulle

loadRowList()

zwraca tablicę numeryczną tablicy numerycznych reprezentujących rekordy tabeli:

. . .
$db->setQuery($query);
$row = $db->loadRowList();
print_r($row);

otrzymamy (spacje dodane dla zwiększenia czytelności):

Array ( 
[0] => Array ( [0] => 1 [1] => John Smith [2] => johnsmith@domain.example [3] => johnsmith ) 
[1] => Array ( [0] => 2 [1] => Magda Hellman [2] => magda_h@domain.example [3] => magdah ) 
[2] => Array ( [0] => 3 [1] => Yvonne de Gaulle [2] => ydg@domain.example [3] => ydegaulle ) 
)

Jako że pracujemy z tablicami numerycznymi, to pojedynczych tablic dostęp uzyskamy poprzez np. $row[0], a do samej wartości poprzez np. #row[0][1].

Uwagi:

  1. Indeksy w tablicy zaczynają się od zera.[!!!]

loadAssocList()

loadAssocList() zwraca asocjacyjną tablicę asocjacyjnych tablic rekordów z tabeli:

. . .
$db->setQuery($query);
$row = $db->loadAssocList();
print_r($row);

otrzymamy (spacje dodane dla zwiększenia czytelności):

Array ( 
[0] => Array ( [id] => 1 [name] => John Smith [email] => johnsmith@domain.example [username] => johnsmith ) 
[1] => Array ( [id] => 2 [name] => Magda Hellman [email] => magda_h@domain.example [username] => magdah ) 
[2] => Array ( [id] => 3 [name] => Yvonne de Gaulle [email] => ydg@domain.example [username] => ydegaulle ) 
) 

Analogicznie do poprzedniego przykładu, dostęp do wiersza np. $row[0], a do wartości np.: $row[0]['name'].

loadAssocList($key)

loadAssocList('key') zwraca asocjacyjną tablicę - indeksu 'key' - oraz asocjacyjnej tablicy składającej się z pozostałej części tabeli:

. . .
$db->setQuery($query);
$row = $db->loadAssocList('username');
print_r($row);

otrzymamy (spacje dodane dla zwiększenia czytelności):

Array ( 
[johnsmith] => Array ( [id] => 1 [name] => John Smith [email] => johnsmith@domain.example [username] => johnsmith ) 
[magdah] => Array ( [id] => 2 [name] => Magda Hellman [email] => magda_h@domain.example [username] => magdah ) 
[ydegaulle] => Array ( [id] => 3 [name] => Yvonne de Gaulle [email] => ydg@domain.example [username] => ydegaulle ) 
)

Aby wywołać sam wiersz: $row['johnsmith'], a samą wartość $row['johnsmith']['name'].

Uwaga: Klucz musi być nazwą jednej z kolumn, w przeciwnym razie zamiast niego zostanie wykorzystany indeks albo klucz główny. Jeśli jednak w tabeli nie ma unikalnego klucza, wyniki będą prezentowanie bez indeksu asocjacyjnego.

loadObjectList()

loadObjectList() zwraca tablicę obiektów PHP reprezentujących pojedyncze rekordy

. . .
$db->setQuery($query);
$row = $db->loadObjectList();
print_r($row);

otrzymamy (spacje dodane dla zwiększenia czytelności):

Array ( 
[0] => stdClass Object ( [id] => 1 [name] => John Smith 
    [email] => johnsmith@domain.example [username] => johnsmith ) 
[1] => stdClass Object ( [id] => 2 [name] => Magda Hellman 
    [email] => magda_h@domain.example [username] => magdah ) 
[2] => stdClass Object ( [id] => 3 [name] => Yvonne de Gaulle 
    [email] => ydg@domain.example [username] => ydegaulle ) 
)

Dostęp do pojedynczych wierszy np.: $row[0], a do wartości np.: $row[0]->name.

loadObjectList('key')

loadObjectList($key) zwraca asocjacyjną tablicę - indeksu 'key' - oraz obiektu utworzonego z pozostałej części tabeli:

. . .
$db->setQuery($query);
$row = $db->loadObjectList('username');
print_r($row);

otrzymamy (spacje dodane dla zwiększenia czytelności):

Array ( 
[johnsmith] => stdClass Object ( [id] => 1 [name] => John Smith 
    [email] => johnsmith@domain.example [username] => johnsmith ) 
[magdah] => stdClass Object ( [id] => 2 [name] => Magda Hellman 
    [email] => magda_h@domain.example [username] => magdah ) 
[ydegaulle] => stdClass Object ( [id] => 3 [name] => Yvonne de Gaulle 
    [email] => ydg@domain.example [username] => ydegaulle ) 
)

Dostęp do pojedynczych wierszy np.: $row['johnsmith'], a do wartości np.: $row['johnsmith']->name.

Uwaga: Klucz musi być nazwą jednej z kolumn, w przeciwnym razie zamiast niego zostanie wykorzystany indeks albo klucz główny. Jeśli jednak w tabeli nie ma unikalnego klucza, wyniki będą prezentowanie bez indeksu asocjacyjnego.

Różne metody wyników

getNumRows()

getNumRows() zwraca liczbę wierszy znalezionych podczas ostatniego zapytania i oczekujących na odczytanie. Aby uzyskać wynik poprzez getNumRows(), musisz wywołać przed i po zapytaniu.

. . .
$db->setQuery($query);
$db->query();
$num_rows = $db->getNumRows();
print_r($num_rows);
$result = $db->loadRowList();
otrzymamy
3

Uwaga: jeśli wywołasz getNumRows() przed loadRowList() - lub inne metody odpowiedzialne za pobieranie - możesz otrzymać ostrzeżenie PHP:

Warning: mysql_num_rows(): 80 is not a valid MySQL result resource 
in libraries\joomla\database\database\mysql.php on line 344
© Ten materiał jest dokładnym albo swobodnym tłumaczeniem artykułu http://docs.joomla.org/Selecting_data_using_JDatabase udostępnionego na licencji JEDL na witrynie: Oficjalnej dokumentacji Joomla!.Pierwszy autor oryginału: Wilsonge.
© Tłumaczenie: Procek. Tłumaczenie wykonano na warunkach licencji JEDL.

Dziękujemy za wkład

» Stefan Wajda [zwiastun],