30 dniowy kurs php – dzień 19 – obsługa błędów


Back-end (php, mysql)

Pisząc kod zdarza się popełnić jakiś błąd. To normalne. Sztuką jednak jest odnalezienie i poprawienie tego błędu. PHP wyciąga do nas pomocną dłoń informując zawsze jakiego typu wystąpił błąd i gdzie go szukać.

Przetestujmy bardzo prosty kod:

<?php
echo $test;
?>

Jako, że zmienna $test nie została zdefiniowana, a chcemy ją wywołać dostaniemy błąd:

Notice: Undefined variable: test in C:\wamp\www\KursPHP\dzien19\index.php on line 2

Powyższy błąd mówi nam w zasadzie wszystko co jest potrzebne do jego naprawienia. Po kolei:

  • Notice – jest to typ błędu jaki wystąpił.
  • Undefined variable: test – powód wystąpienia błędu, czyli niezidentyfikowana zmienna test
  • in C:\wamp\www\KursPHP\dzien19\index.php – lokalizacja pliku, w którym wystąpił błąd
  • on line 2 – nr linii, w której wystąpił błąd

Dzięki powyższym informacjom naprawienie błędu jest jak widzisz bardzo proste. Taki błąd nie jest jednak miłym widokiem w funkcjonującym serwisie. Dodatkowo wyświetlenie pełnej ścieżki pliku nie jest też pożądane ze względów bezpieczeństwa. Warto więc stworzyć własną funkcję obsługi błędów. Na początek kilka istotnych informacji.

Typy błędów

W powyższym przykładzie mieliśmy błąd typu Notice. Typów tych błędów jest więcej, a najczęściej spotykane znajdziesz w poniższej tabeli:

Wartość Stała Opis
1 E_ERROR Fatalny błąd wykonywania skryptu. Oznacza błąd na poziomie systemu jak np. problemy z przydziałem pamięci. Wykonywanie skryptu zostaje zatrzymane
2 E_WARNING Ostrzeżenie. Nie fatalny błąd. Wykonywanie skryptu nie zostanie zatrzymane
8 E_NOTICE Uwaga w czasie wykonywania skryptu. Może być błędem, ale może też wystąpić w czasie normalnego wykonywania skryptu
256 E_USER_ERROR Fatalny błąd generowany z winy użytkownika. Podobny do E_ERROR, ale ustawiany przez programistę za pomocą funkcji trigger_error()
512 E_USER_WARNING Ostrzeżenie. Nie fatalny błąd. Tak jak E_WARNING, tylko ustawiany przez programistę za pomocą funkcji trigger_error()
1024 E_USER_NOTICE Uwaga generowana na polecenie użytkownika. Tak jak E_NOTICE, tylko ustawiana przez programistę za pomocą funkcji trigger_error()
4096 E_RECOVERABLE_ERROR Przechwycony fatalny błąd. Tak jak E_ERROR, tylko może zostać wyłapany przez zdefiniowanie obsługi błędów.
8191 E_ALL Wszystkie rodzaje ostrzeżeń i błędów, za wyjątkiem poziomu E_STRICT.

Wszystkie możliwe rodzaje błędów znajdziesz w podręczniku php.

Własna obsługa błędów

Na początek pokażę Ci jak kompletnie wyłączyć wyświetlanie błędów:

<?php
error_reporting(0);

echo $test;
?>

Zamiast błędu typu Notice, który wcześniej nam się pojawiał nie zobaczymy żadnego błędu. Funkcja error_reporting() pozwala na ustalenie jaki typ błędów ma się pojawiać. 0 symbolizuje brak wyświetlania jakichkolwiek błędów. Błędy to jednak ważny element poprawnie działającej strony. Możemy jednak ustalić wyświetlanie wszystkich błędów oprócz błędów typu Notice.

<?php
error_reporting(E_ALL ^ E_NOTICE);

echo $test;
?>

Znak ^ oznacza „z wyjątkiem”. Czyli raportowanie błędów ustawiamy na wyświetl wszystkie z wyjątkiem błędów E_NOTICE.

Pora na funkcję, w której zdefiniujemy tekst, który będzie wyświetlał nam się w zależności od błędów.

<?php

function zdefiniowaneBledy($errno, $errstr)
{
 echo "<b>Error:</b> [$errno] $errstr<br />";
 die ('Skrypt zatrzymany');
}
set_error_handler('zdefiniowaneBledy');

echo $test; 
?>

Stworzyliśmy funkcję o nazwie zdefioniowaneBledy. Następnie używamy funkcji do obsługi błędów set_error_handler() w której podajemy w nawiasie nazwę  utworzonej wcześniej funkcji. Efekt:

Error: [8] Undefined variable: test
Skrypt zatrzymany

Nie mamy tak jak wcześniej ścieżki pliku mamy tylko nr wartości błędu (8 dla E_NOTICE) i opis błędu czyli niezidentyfikowana zmienna test.

Wywoływanie błędów

Możemy również sami ustalić w którym miejscu skryptu stworzymy własny błąd. Jeśli stworzymy np. konstrukcję if, której spełnienie warunku jest koniecznie do dalszego działania skryptu, możemy wymusić wystąpienie błędu. Przykład:

<?php

function zdefiniowaneBledy($errno, $errstr)
{
 echo "<b>Error:</b> [$errno] $errstr<br />";
 die ('Skrypt zatrzymany');
}
set_error_handler('zdefiniowaneBledy');

$test = 2;
if ($test > 1)
{
 trigger_error('$test > 1');
}

?>

Dzięki temu wyświetli nam się błąd:

Error: [1024] $test > 1
Skrypt zatrzymany

Zapisywanie błędów/wysyłanie na e-mail

Za pomocą funkcji error_log() możemy skonfigurować automatyczną wysyłkę e-maili w przypadku wystąpienia błędu. Dzięki temu, jeśli strona nie będzie funkcjonować prawidłowo zostaniemy o tym powiadomieni.

Możemy też wszystkie błędy zapisywać automatycznie do pliku, który raz na jakiś czas przejrzymy w poszukiwaniu błędów.

W poniższym kodzie wysyłamy na e-mail informację o błędzie:

<?php

function zdefiniowaneBledy($errno, $errstr)
{
 echo "<b>Error:</b> [$errno] $errstr<br />";
 error_log("Error: [$errno] $errstr", 1, "[email protected]");
 die ('Skrypt zatrzymany');
}
set_error_handler('zdefiniowaneBledy');

$test = 2;
if ($test > 1)
{
 trigger_error('$test > 1');
}

?>

error_log() ma następujące możliwe parametry:

error_log ( treść błędu/wiadomości , typ wiadomości (0, 1, 3, 4) , przeznaczenie (zależne od podanego typu wiadomości) , dodatkowy nagłówek (tylko w przypadku typu 1) )

Gdzie typ wiadomości wygląda następująco:

  • 0 – domyślna opcja, błędy wysyłane do systemu logów PHP
  • 1 – wiadomość wysyłana e-mailem (w przeznaczeniu podajemy adres e-mal i opcjonalnie nagłówki wiadomości)
  • 2 – obecnie nie istnieje jako opcja
  • 3 – wiadomość zapisywana jest do pliku (ścieżka i nazwa pliku podawana w przeznaczeniu)
  • 4 – błąd wysyłany bezpośrednio do SAPI

Możemy więc zamiast wysyłać błędy na e-mail, zapisywać je do wybranego pliku:

<?php
error_log("Error: [$errno] $errstr", 3, "/sciezka/error.log");
?>

Sposobów na radzenie sobie z błędami jest wiele. Można wyłapywać poszczególnego rodzaje błędów przy pomocy konstrukcji switch. Więcej na ten temat znajdziesz w dokumentacji php.