← Lekcje
PHP · lekcja 24

Błędy w PHP:
cztery rodzaje

Dzisiaj:

  1. Cztery rodzaje: błąd składni, ostrzeżenie, błąd krytyczny i wyjątek - czym się różnią
  2. Jak czytać komunikat błędu? Typ, treść, plik, linia
  3. error_reporting i display_errors - gdzie w XAMPP chowają się błędy
  4. Ćwiczenie: naprawiamy plik z trzema różnymi błędami
Rozgrzewka · 3 minuty

Rozgrzewka: include, require

  1. Czym różni się reakcja PHP na brakujący plik przy include a przy require?
  2. Po co używamy require_once zamiast zwykłego require?
  3. Dlaczego do connect-database.php lepiej pasuje require niż include?
Część 1 · Czytamy komunikat błędu

Anatomia komunikatu błędu

Za każdym razem, gdy PHP zgłasza błąd, mówi wam cztery rzeczy naraz: jaki to typ błędu, jaka jest jego treść (co dokładnie się nie udało), w którym pliku i w której linii kodu. Nauczcie się czytać te cztery elementy po kolei - to najszybsza droga do naprawy, szybsza niż zgadywanie.

Warning: Undefined variable $name in C:\xampp\htdocs\nazwisko\greeting.php on line 7 TYP rodzaj błędu TREŚĆ co dokładnie się nie udało PLIK gdzie szukać w kodzie LINIA która linia w pliku
Część 2 · Cztery rodzaje

Cztery rodzaje błędów w PHP

RodzajKiedy się pojawiaCo się dzieje ze stroną
Błąd składni (Parse error)zanim PHP zacznie wykonywać kod - literówka, brak średnikażadna linia kodu się nie wykonuje
Ostrzeżenie (Warning)w trakcie działania, np. brak zmiennejstrona jedzie dalej
Błąd krytyczny (Fatal error)w trakcie działania, np. brak funkcjistrona zatrzymuje się w tym miejscu
Wyjątek złapany w try...catchbłąd krytyczny, ale obsłużony wcześniejstrona jedzie dalej
PHP Manual: language.errors.basics.php („PHP reports errors in response to a number of internal error conditions... Every error that PHP generates includes a type.”)
Część 3 · Waga błędu

Od ostrzeżenia do błędu krytycznego

PHP wykrywa błąd składni, zanim uruchomi choćby jedną linię kodu - dlatego widzicie tylko jeden taki komunikat na raz. Ostrzeżenie i błąd krytyczny pojawiają się już w trakcie działania strony. Różnią się tym, czy PHP jedzie dalej, czy się zatrzymuje - a błąd krytyczny złapany w try...catch jednak pozwala jechać dalej.

BŁĄD SKŁADNI Parse error PHP nie wykona ani jednej linii - błąd wykryty zanim skrypt wystartuje poza drabinką - jeszcze przed uruchomieniem bez błędu składni OSTRZEŻENIE (Warning) skrypt jedzie dalej jedna linia się nie udała BŁĄD KRYTYCZNY Fatal error skrypt zatrzymuje się tutaj jeśli złapany ZŁAPANY W try...catch to już wyjątek - obsłużony skrypt jednak jedzie dalej
PHP Manual: errorfunc.constants.php (tabela poziomów błędów E_ERROR/E_WARNING/E_PARSE)
Część 4 · Gdzie się chowają błędy

error_reporting i display_errors

UstawienieCo robiDomyślnie
display_errorspokazuje błędy na stronie w przeglądarcewłączone
log_errorszapisuje błędy do dziennika zamiast (albo obok) pokazywaniawyłączone
error_logplik dziennika; puste = dziennik serwera (w XAMPP: Apache → logs → error.log)puste
error_reportingustala, które poziomy błędów w ogóle są zgłaszaneod PHP 8.0: wszystkie (E_ALL)

Ta sama linia z części „Cztery rodzaje” już nie pokazuje ostrzeżenia, gdy na początku pliku dodacie error_reporting(0):

error_reporting(0);
echo "Cześć, " . $name . "!";
// result: "Cześć, !" - bez komunikatu Warning, zmienna nadal jest pusta
PHP Manual: errorfunc.configuration.php („display_errors ... This determines whether errors should be printed to the screen...”, „log_errors ... Tells whether script error messages should be logged...”), function.error-reporting.php
Część 5 · Łapiemy błąd

try...catch: łapiemy błąd

Niektóre błędy krytyczne w PHP to tak naprawdę wyjątki - obiekty, które można złapać, zanim zatrzymają całą stronę. Kod, który może się wysypać, otaczacie blokiem try { ... }. Jeśli PHP rzuci wyjątek pasującego typu, wykonanie przeskakuje do catch (Typ $e) { ... }, a reszta strony działa dalej.

try { ... } divide(10, 0); kod, który może się wysypać czy PHP rzucił wyjątek? nie tak catch (DivisionByZeroError $e) echo "Błąd: " . $e->getMessage(); wypisze: Błąd: Division by zero strona nie zatrzymuje się reszta programu skrypt działa dalej

Ciekawostka z PHP Manual: od PHP 7 większość dawnych błędów krytycznych PHP zgłasza jako obiekty klasy Error, a nie starym mechanizmem, który po prostu zatrzymywał skrypt. Dzięki temu można je złapać blokiem try...catch, tak jak w tym przykładzie DivisionByZeroError.

PHP Manual: language.exceptions.php („An exception can be thrown, and caught (\"caught\") within PHP. Code may be surrounded in a try block...”) · ciekawostka: PHP Manual, language.errors.php7.php („PHP 7 changes how most errors are reported by PHP... most errors are now reported by throwing Error exceptions”), php.net/manual/en/language.errors.php7.php
Egzamin INF.03

Tak pytają na egzaminie

1. W aplikacji PHP obsługującej bazę danych, aby po wykonaniu dowolnej operacji otrzymać numer błędu oraz jego opis, należy zastosować

  1. tylko funkcję mysqli_error
  2. funkcje mysqli_error i mysqli_errno
  3. funkcje mysqli_error i mysqli_error_number
  4. funkcje mysqli_error i mysqli_connect_errno

2. Błędy interpretacji kodu PHP są zapisywane

  1. w logu pod warunkiem ustawienia odpowiedniego parametru w pliku php.ini
  2. w podglądzie zdarzeń systemu Windows
  3. w oknie edytora, w którym powstaje kod PHP
  4. ignorowane przez przeglądarkę oraz interpreter kodu PHP
CKE, EE.09, styczeń 2022, zadanie 27 · CKE, E.14, styczeń 2016, zadanie 39 (bank pytań, przedmiot strony, temat php)
Ćwiczenie przy komputerze · 15 minut

Ćwiczenie: errors-to-fix.php

  1. Utwórz w folderze swojego serwera plik errors-to-fix.php i przepisz do niego kod z ramki „Plik do naprawy” pod instrukcją.
  2. Otwórz localhost/errors-to-fix.php w przeglądarce - zobaczysz pierwszy komunikat błędu.
  3. Napraw ten jeden błąd, zapisz plik, odśwież stronę - pojawi się kolejny komunikat, innego typu.
  4. Powtarzaj naprawę i odświeżanie, aż strona wypisze wynik bez żadnego komunikatu błędu.
  5. Na końcu pliku, w komentarzu, zapisz krótko, jakie trzy błędy naprawiłeś i jakiego były typu.

W pliku są trzy błędy różnych typów: jeden błąd składni, jedno ostrzeżenie, jeden błąd krytyczny.

Plik do naprawy
$price = 19.90
$discount = 0.10;

echo "Cena po rabacie: " . ($price - $quantity) . " zł\n";

echo calculateTax($price);
Cały plik
// błąd 1 (błąd składni): brakujący średnik po 19.90
$price = 19.90; // naprawione: dopisany średnik
$discount = 0.10;
$quantity = 3; // błąd 2 (ostrzeżenie): brakująca zmienna $quantity - dopisana

// błąd 3 (błąd krytyczny): brakująca funkcja calculateTax() - dopisana
function calculateTax($price) {
    return $price * 0.23;
}

echo "Cena po rabacie: " . ($price - $quantity) . " zł\n";
echo calculateTax($price);
// result: Cena po rabacie: 16.9 zł
// result: 4.577

Trzy naprawione błędy, w kolejności napotkania: błąd składni, ostrzeżenie, błąd krytyczny.

Na koniec

Sprawdź się

  1. Czym różni się reakcja PHP na ostrzeżenie a na błąd krytyczny?
  2. Dlaczego błąd składni blokuje zobaczenie jakiegokolwiek innego błędu w tym samym pliku?
  3. Po co używać try...catch, skoro błąd krytyczny i tak pojawiłby się na ekranie?

Na następnej lekcji: powtórka całego działu PHP.

Poza szkołą

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
display_errors włączone - błąd widać na stroniedisplay_errors wyłączone, log_errors włączone - błąd trafia do pliku, użytkownik widzi neutralną stronę.nadal w użyciu
Błąd krytyczny zatrzymuje całą stronę bez obsługiFramework (np. Laravel) łapie każdy błąd centralnie i pokazuje jedną spójną stronę błędu.narzędzia
Czytamy komunikat „na oko” w przeglądarce albo w pliku logaNarzędzie do monitoringu błędów (np. Sentry) grupuje błędy i wysyła powiadomienie o nowych.narzędzia
PHP Manual: errorfunc.configuration.php