← Lekcje
PHP · lekcja 22

Bazy danych 5/5: gdy zapytanie się nie uda

Dzisiaj:

  1. Krótka powtórka całego tematu: connectSELECTINSERTUPDATE/DELETE
  2. mysqli_error() mówi, co poszło nie tak, gdy zapytanie zawiedzie
  3. mysqli_insert_id() - tylko po udanym zapytaniu wskazuje właściwy wiersz
  4. Ćwiczenie: dopisujemy obsługę błędu do add-product.php - podsumowanie tematu
Rozgrzewka · 3 minuty

Rozgrzewka: UPDATE, DELETE, WHERE

  1. Czym różni się skutek UPDATE od skutku DELETE na tym samym wierszu?
  2. Co się stanie, jeśli wykonasz DELETE FROM products bez klauzuli WHERE?
  3. Co oznacza wynik 0 zwrócony przez mysqli_affected_rows()?
Część 1 · Cały temat w jednym obrazku

Pięć godzin baz danych: powtórka

Cztery godziny tego tematu pokazały cztery operacje na tabeli products: połączenie, odczyt, dopisanie i zmianę/usunięcie wiersza. Zostaje jedna rzecz, której jeszcze nie mieliśmy - co zrobić, gdy któraś z tych operacji się nie powiedzie.

connect połączenie z bazą godzina 1 connect-database.php SELECT odczyt wierszy godzina 2 product-list.php INSERT dopisanie wiersza godzina 3 add-product.php UPDATE / DELETE zmiana lub usunięcie wiersza godzina 4 update/delete-product.php obsługa błędu gdy któraś z operacji wyżej się nie powiedzie godzina 5 - dzisiaj mysqli_error()
Część 2 · Gdy zapytanie się nie uda

Zapytanie zawiodło - mysqli_error() mówi, co poszło nie tak

Zapisz wynik mysqli_query() do zmiennej. Gdy zapytanie się nie udało (na przykład literówka w nazwie kolumny), funkcja zwraca false. Wtedy mysqli_error($db) zwraca opis błędu z bazy - gdy błędu nie było, zwraca pusty ciąg znaków.

$wynik = mysqli_query( $db, $zapytanie) zapytanie się nie udało $wynik to false if (!$wynik) wchodzimy do środka tylko gdy błąd wystąpił echo mysqli_error($db); przykład z PHP Manual (zapytanie testowe SET a=1): Unknown system variable 'a' brak błędu → mysqli_error() zwraca pusty ciąg "" treść błędu dla products: do sprawdzenia w sali

Ciekawostka z PHP Manual: od PHP 8.1 mysqli domyślnie nie zwraca już false przy błędzie, tylko rzuca wyjątek. Dlatego kod w tej lekcji zaczyna się od mysqli_report(MYSQLI_REPORT_OFF) - włącza starszy tryb, w którym wynik trzeba sprawdzić samodzielnie, tak jak uczy ta lekcja.

PHP Manual: mysqli.error.php („Returns a string that describes the last error… empty string if no error occurred”, przykład if (!$mysqli->query("SET a=1")) { printf("Errormessage: %s\n", $mysqli->error); }Unknown system variable 'a', php.net/manual/en/mysqli.error.php) · ciekawostka: PHP Manual, mysqli-driver.report-mode.php („The default value is now MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT. Previously, it was MYSQLI_REPORT_OFF”, zmiana w PHP 8.1.0), php.net/manual/en/mysqli-driver.report-mode.php
Część 3 · Gdy zapytanie się udało

Zapytanie się udało - mysqli_insert_id() wskazuje nowy wiersz

Gdy $result nie jest false, zapytanie INSERT się udało. Dopiero wtedy warto odczytać mysqli_insert_id($db) - zwraca numer id wiersza, który właśnie dodałeś. Wywołana zaraz po nieudanym zapytaniu funkcja zwróci 0, bo żaden nowy wiersz nie powstał.

id name price 1 Kubek 19.90 2 Długopis 4.20 4 Zakreślacz 6.00 5 Gumka 2.50 nowy mysqli_insert_id($db) zapytanie się udało → zwraca 5 (id nowego wiersza) zapytanie się nie udało → zwraca 0, bo żaden wiersz nie powstał
PHP Manual: mysqli.insert-id.php („Returns the auto generated id used in the latest query… Zero if the previous query does not use an AUTO_INCREMENT value”, php.net/manual/en/mysqli.insert-id.php)
Egzamin INF.03

Tak pytają na egzaminie

1. W bibliotece mysqli języka PHP, aby uzyskać ostatni komunikat o błędzie można zastosować funkcję

  1. mysqli_error()
  2. mysqli_errno()
  3. mysqli_error_list()
  4. mysqli_use_result()

2. Pole insert_id zdefiniowane w bibliotece MySQLi języka PHP może być wykorzystane do

  1. otrzymania id ostatnio wstawionego wiersza.
  2. otrzymania kodu błędu, gdy proces wstawiania wiersza się nie powiódł.
  3. pobrania najwyższego indeksu bazy, aby po jego inkrementacji wstawić pod niego dane.
  4. pobrania pierwszego wolnego indeksu bazy, tak, aby można było pod nim wstawić nowe dane.
CKE, EE.09, styczeń 2023, zadanie 10 · CKE, EE.09, czerwiec 2021, zadanie 25
Ćwiczenie przy komputerze · 15 minut

Ćwiczenie: obsługa błędu w add-product.php

  1. Otwórz add-product.php z lekcji „Bazy danych 3/5” w folderze htdocs swojego serwera. Zapisz wynik zapytania do zmiennej: $result = mysqli_query($db, $query);
  2. Dodaj: if (!$result) { echo mysqli_error($db); }
  3. W przeciwnym przypadku (zapytanie się udało) wypisz: echo "Dodano produkt nr " . mysqli_insert_id($db);
  4. Sprawdź w przeglądarce: localhost/add-product.html, wypełnij formularz - powinieneś zobaczyć numer nowego wiersza. Potem celowo zepsuj nazwę kolumny w zapytaniu i sprawdź, czy pokazuje się komunikat błędu; następnie napraw kod z powrotem.
  5. Zapisz plik - to podsumowanie całego tematu baz danych. Jeśli prowadzisz repozytorium, zrób commit „Dodaje obsługę błędu do add-product.php”.
Na koniec

Sprawdź się

  1. Co trzeba zrobić z wynikiem mysqli_query(), zanim sprawdzisz, czy zapytanie się udało?
  2. Co zwraca mysqli_error($db), gdy zapytanie się udało?
  3. Dlaczego mysqli_insert_id() wywołana po nieudanym INSERT zwróci 0?

To zamyka temat baz danych: connect, SELECT, INSERT, UPDATE, DELETE i obsługa błędu. Na następnej lekcji: nowy temat - dzielimy kod na pliki (include i require).

Poza szkołą

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
Błąd zapytania sprawdzany ręcznie po każdym mysqli_query()PDO albo mysqli w trybie wyjątków - błąd sam przerywa program, nie trzeba go sprawdzać w każdym miejscu.zastępowane (frameworkiem)
echo mysqli_error($db) wprost na stronieBłąd trafia do logu serwera, użytkownik widzi ogólny komunikat - szczegóły bazy danych nie powinny być widoczne publicznie.nadal w użyciu (bezpieczeństwo)
mysqli_insert_id() odczytywana ręcznie zaraz po INSERTORM zwraca gotowy obiekt nowego rekordu z już wypełnionym id, bez osobnego wywołania.zastępowane (frameworkiem)
Jeden plik add-product.php na jedną operacjęWarstwa dostępu do danych (repozytorium/model) grupuje wszystkie zapytania do jednej tabeli w jednym miejscu.nadal w użyciu
PHP Manual: mysqli.error.php, mysqli.insert-id.php