← Lekcje
PHP · lekcja 19

Bazy danych 2/5: pobieramy dane zapytaniem SELECT

Dzisiaj:

  1. Zakładamy tabelę products razem, z kilkoma przykładowymi wierszami
  2. Zapytanie SELECT wybiera tylko potrzebne kolumny i wiersze z tabeli
  3. Funkcje mysqli_query() i mysqli_fetch_assoc() pobierają wynik do PHP
  4. Ćwiczenie: wypisujemy wszystkie produkty z bazy shop
Rozgrzewka · 3 minuty

Rozgrzewka: baza, tabela i połączenie

  1. Co to jest wiersz w tabeli bazy danych, np. w tabeli produktów?
  2. Jakie są cztery pierwsze parametry funkcji mysqli_connect() i w jakiej kolejności?
  3. Co zwraca mysqli_connect(), gdy połączenie się nie powiedzie?
Część 1 · Zakładamy tabelę razem

Tabela products z kilkoma wierszami

W phpMyAdmin, w bazie shop, zakładamy tabelę products z trzema kolumnami: id (numer, sam się zwiększa), name (nazwa produktu) i price (cena). Zanim napiszemy jakikolwiek kod PHP, wpisujemy do niej ręcznie kilka wierszy - bez danych SELECT nie ma czego zwrócić.

idnameprice
1Kubek19.90
2Długopis3.50
3Zeszyt7.20
MariaDB KB: create-table (mariadb.com/kb/en/create-table/) - struktura tabeli
Część 2 · Zapytanie SELECT

SELECT jako sito nad tabelą

SELECT nie zmienia tabeli - tylko wybiera z niej to, co pasuje. Wybieramy kolumny po przecinku (albo * - wszystkie) i, jeśli trzeba, warunek WHERE na wierszach. Przechodzą tylko wiersze, które ten warunek spełniają.

tabela products id name price 1 Kubek 19.90 2 Długopis 3.50 3 Zeszyt 7.20 4 Plecak 89.00 SELECT name, price FROM products WHERE price < 10 wynik SELECT name price Długopis 3.50 Zeszyt 7.20 (Kubek i Plecak odpadły - cena ≥ 10)

Ciekawostka z Wikipedii: język SQL, w którym piszemy SELECT, nazywał się kiedyś SEQUEL. Zaprojektowali go w IBM na początku lat 70. XX wieku Donald Chamberlin i Raymond Boyce, ale nazwę trzeba było skrócić do SQL, bo SEQUEL był już zastrzeżonym znakiem towarowym brytyjskiej firmy Hawker Siddeley.

MariaDB Server: „SELECT is used to retrieve rows selected from one or more tables”; „The WHERE clause, if given, indicates the condition or conditions that rows must satisfy to be selected.” (mariadb.com/docs/server/reference/sql-statements/data-manipulation/selecting-data/select) · ciekawostka: Wikipedia, „SQL was initially developed at IBM by Donald D. Chamberlin and Raymond F. Boyce after learning about the relational model from Edgar F. Codd in the early 1970s. This version, initially called SEQUEL (Structured English Query Language), was designed to manipulate and retrieve data stored in IBM's original quasirelational database management system, System R.”; „The original name SEQUEL ... was later changed to SQL (dropping the vowels) because "SEQUEL" was a trademark of the UK-based Hawker Siddeley Dynamics Engineering Limited company.” · en.wikipedia.org/wiki/SQL
Część 3 · Od zapytania do strony

Droga zapytania: PHP → MariaDB → wynik → HTML

mysqli_query() wysyła zapytanie do MariaDB i „gdy zapytanie tworzy zestaw wyników (np. SELECT), zwraca obiekt mysqli_result” (PHP Manual). mysqli_fetch_assoc() wyciąga z tego obiektu jeden wiersz jako tablicę, gdzie kluczami są nazwy kolumn.

PHP mysqli_query($db, "SELECT…") MariaDB wykonuje zapytanie na tabeli products wynik obiekt mysqli_result mysqli_fetch_assoc() wyciąga jeden wiersz ["name"=>"Kubek", "price"=>19.90] HTML echo w pętli buduje listę na stronie
PHP Manual: „mysqli_query: for successful queries which produce a result set… mysqli_query() will return a mysqli_result object” (php.net/manual/en/mysqli.query.php) · „mysqli_fetch_assoc() fetches one row of data from the result set and returns it as an associative array” (php.net/manual/en/mysqli-result.fetch-assoc.php)
Część 4 · Kod na żywo

Pętla while czyta wiersz po wierszu

Jedno wywołanie mysqli_fetch_assoc() daje jeden wiersz. „Każde kolejne wywołanie zwróci następny wiersz z wyniku, albo null, gdy wierszy już nie ma” (PHP Manual) - a null w warunku while zachowuje się jak „nie”, więc pętla sama się zatrzymuje.

// pobieramy wszystkie produkty
$result = mysqli_query($db, "SELECT * FROM products");
while ($row = mysqli_fetch_assoc($result)) {
    echo $row["name"] . " - " . $row["price"] . " zł<br>";
}
// gdy fetch_assoc zwróci null, warunek jest fałszywy - pętla się kończy
Kubek 19.90 Długopis 3.50 Zeszyt 7.20 wynik, wiersz po wierszu mysqli_fetch_assoc() bierze jeden wiersz na raz $row echo w pętli null koniec, while stop
PHP Manual: „Each subsequent call to this function will return the next row within the result set, or null if there are no more rows” (php.net/manual/en/mysqli-result.fetch-assoc.php)
Egzamin INF.03

Tak pytają na egzaminie

1. $tab = mysqli_query($db, "SELECT imie FROM Osoby WHERE wiek < 18"); W języku PHP wykonano operację przedstawioną w ramce. Aby wyświetlić wszystkie wyniki tego zapytania, należy

  1. wyświetlić zmienną $db
  2. zastosować polecenie mysql_fetch
  3. zastosować pętlę z poleceniem mysqli_fetch_row
  4. zaindeksować zmienną tab, tab[0] to pierwsze imię

2. $query = mysqli_query($db, "SELECT imie, nazwisko FROM uzytkownik"); $count = mysqli_num_rows($query); for ($i = 0; $i < $count; $i++) { $row = ………; echo "$row[0] $row[1]"; } W miejscu kropek powinno znaleźć się polecenie

  1. mysqli_fetch_row($query);
  2. mysqli_free_result($query);
  3. mysqli_num_fields($query);
  4. mysqli_query($query);
CKE, E.14, styczeń 2020, zadanie 38 · CKE, E.14, czerwiec 2018, zadanie 39
Ćwiczenie przy komputerze · 15 minut

Ćwiczenie: lista produktów z bazy

  1. Sprawdź w phpMyAdmin, że tabela products w bazie shop ma kilka wierszy (założona razem na tej lekcji).
  2. W folderze swojego serwera (np. htdocs) utwórz plik product-list.php.
  3. Połącz się z bazą tak jak w connect-database.php (mysqli_report, mysqli_connect, if (!$db) die(...)).
  4. Wykonaj mysqli_query($db, "SELECT * FROM products") i w pętli while z mysqli_fetch_assoc() wypisz name i price każdego wiersza.
  5. Otwórz localhost/product-list.php - ma pokazać listę produktów.
Na koniec

Sprawdź się

  1. Co robi funkcja mysqli_query() i co zwraca dla zapytania SELECT?
  2. Co zwraca mysqli_fetch_assoc(), gdy w wyniku nie ma już żadnego wiersza?
  3. Dlaczego pętla while ($row = mysqli_fetch_assoc($result)) sama się zatrzymuje po ostatnim wierszu?

Na następnej lekcji: zapisujemy dane z formularza do bazy poleceniem INSERT.

Poza szkołą

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
SELECT * - pobiera wszystkie kolumnyPobiera się tylko potrzebne kolumny (SELECT name, price) - mniej danych do przesłania i przetworzenia.nadal w użyciu (dobra praktyka)
mysqli_fetch_assoc() w pętli whileORM (mapowanie obiektowo-relacyjne, np. Eloquent w Laravel) zwraca od razu gotowe obiekty zamiast tablic asocjacyjnych.zastępowane (frameworkiem)
Wynik zapytania wypisywany echo wprost w pętliDane zamieniane na JSON (format tekstowy do przesyłania danych) i renderowane po stronie przeglądarki przez JavaScript.zastępowane (w aplikacjach jednostronicowych)
Zapytanie SQL wpisane wprost jako tekst w kodzie PHPZapytania przygotowane (mysqli_prepare) chronią przed wstrzyknięciem SQL - temat na później.narzędzia (wyższy poziom)
PHP Manual: mysqli.query.php, mysqli-result.fetch-assoc.php