Wyjątki i obsługa błędów

Dzisiaj raczej krótko i na temat, czyli jak zrobić żeby nawet jak użytkownik popsuje coś na przykład wpisując złe dane w formularzu dostał elegancką informację o tym zamiast dość długiego komunikatu PHP o błędzie, zawierającego informacje, których raczej nie chcielibyśmy pokazywać użytkownikowi.

Dlaczego nie chcemy pokazać użytkownikowi błędów PHP? Z co najmniej trzech powodów:

  1. Jest to nieprofesjonalne i wskazuje na to że oprogramowanie jest niedopracowane.
  2. Wygląda nieestetycznie i wprowadze użytkownika w dezinformacje.
  3. Ujawnia informacje o architekturze naszego oprogramowania, czego lepiej byłoby nie pokazywać przeciętnemu hakerowi, próbującymi zaszkodzić systemowi

Typy błędów PHP

W PHP mamy co najmniej cztery typy błędów:

  • Warning
  • Notice
  • Fatal error
  • Parse error

Ciężko określić które błędy są bardziej uciążliwe, na pewno „Parse error” najłatwiej wykryć w testach ponieważ jeśli na przykład zapomnimy średnika na końcu to program po prostu nie zadziałą co natychmiastowo wymusi jego poprawienie.

Gorzej jest w przypadku „Fatal error” program wprawdzie się skompiluje ale wykona się do momentu wystąpienia błędu. Ten błąd może być spowodowany na przykład próbą użycia nie istniejącej klasy czy funkcji (ten błąd jest szczególnie problematyczny ponieważ tutaj przeważnie wchodzą literówki).

Warningi i Notice zazwyczaj są najmniej problematyczne, jest to po prostu informacja o wystąpieniu problemu. Zazwyczaj podczas uruchomienia aplikacji na środowisku produkcyjnym wyłączamy całkowicie wyświetlanie tego typu błędów aby ostateczny użytkownik ich nie widział. Wprawdzie nie zatrzymują działania aplikacji ale mogą infrmować o błędach, które spowodują błędy w danych a jeśli np chodzi o liczenie pieniędzy może powstać problem. Zawsze sprawdzamy przyczynę pojawienia się takiego błędu.

Wiedząc jakie mamy typy błędów spróbujmy teraz wywołać po jednym z każdego typu.


    $result = 9 / 0;
    echo $result2;
    exampleFunction();
    //echo "green"

W efekcie uzyskamy następujące rezultaty:

    Warning: Division by zero in D:\xampp\htdocs\kurs_php\index.php on line 2
    Notice: Undefined variable: result2 in D:\xampp\htdocs\kurs_php\index.php on line 3
    Fatal error: Uncaught Error: Call to undefined function exampleFunction() in D:\xampp\htdocs\kurs_php\index.php:4 Stack trace: #0 {main} thrown in D:\xampp\htdocs\kurs_php\index.php on line 4
    

Jak widać z powyższego przykładu uzyskaliśmy dokładne informacje o tym jaki błąd, w którym miejscu występuje. Mamy także dość dokładną informację o tym na czym błąd polega, nic tylko poprawiać.

Dzielenie przez zero generuje ostżerzenie, jakby się dobrze zastanowić jest to dość istotny problem ponieważ jeśli w obliczeniu zdarzy się taka sytuacja nie otrzymamy żadnego konkretnego wyniku.

Odniesienie się do nieistniejącej zmiennej powoduje powiadomienie. Warto wiedzieć że ten błąd jest także bardzo często powodowany przez odniesienie się do nieistniejącego indeksu w tablicy.

Próba wywołania nieistniejącej funkcji powoduje Fatal error co spowoduje natychmiastowe zatrzymanie programu. Lepiej żeby taki błąd nie wystąpił podczas przelewu pieniędzy z konta na konto pomiędzy odjęciem z jednego konta a dodaniem na drugie.

W ostatnim przypadku zapmniałem średnika, taki błąd jest problematyczny do tego stopnia że aż go wykomentowałem ponieważ program by się nie skompilował. Oczywiście odkomentowanie tej linijki również wygeneruje błąd Parse error z dość dokładną informacją na temat tego co trzeba poprawić.

Parse error: syntax error, unexpected end of file, expecting ';' or ',' in D:\xampp\htdocs\kurs_php\index.php on line 5

Podstawy konstrukcji TRY – CATCH

Do obsługi wyjątków najczęściej wykorzystujemy konstrukcję TRY – CATCH. Podstawowa konstrukcja wygląda w następujący sposób

<?php
    try {
        //Kod który może zwrócić wyjątek
    } catch (Exception $ex) {
        //wyświetlamy informację o wyjątku
        echo $ex->getMessage();
        //lub podejmujemy jakieś inne działanie
        //header("location:/");
    }
?>

Konstrukcja tego mechanizmu nie jest zbyt skomplikowana. Mamy dwa bloki.

Pierwszy po słowie kluczowym try zawiera kod, który wykonujemy ale może sprawić problemy. Kod w tym bloku jest wykonywany do momentu aż nie wystąpi wyjątek dlatego też trzeba tutaj uważać ponieważ możemy doprowadzić do sytuacji gdy zapisze się tylko część danych do bazy. Może np zdażyć się tak że zostanie dodane zamówienie ale nie zostanie wysłany email z potwierdzeniem i nie zostanie wyświetlona informacja o powodzeniu przez co użytkwonik najprawdopodobniej ponownie złoży zamówienie.

Po zamknięciu pierwszego bloku po słowie catch przechwytujemy wyjątek a następnie podejmujemy dowolną akcję z nim związaną, na przykład wyświetlamy użytkownikowi komunikat albo przekierowujemy na przygotowanoą odpowiednio stronę błędu.

Spróbujmy teraz przechwycić jakiś błąd. Aby to zrobić trzeba napisać trochę błędnego kodu. Spróbujmy wykonać operację mnożenia na ciągach znaków.