Jeżeli jeszcze jej nie czytałeś, zerknij do części pierwszej, aby wiedzieć, o czym piszemy i z czym się „zmagamy”.
Nasz skrypt już się wykonuje, ale wyrzuca nam niezdrowe komunikaty, świadczące o tym, że jakość kodu jest nie najlepsza. Najgroźniej w tej chwili brzmi „Warning”, zajmijmy się tym komunikatem:
1 2 |
<br /> <b>Warning</b>: Division by zero in <b>C:\bin\domeny\test.local\public_html\test_error_reporting.php</b> on line <b>24</b><br /> |
To błąd, który popełnia się rzadko, ale skądś się bierze. Nie wolno dzielić przez zero, wynik takiego działania, zmierza do nieskończoności a nieskończoność nie jest liczbą… a zmierzanie też liczbą nie jest… więc się nie da. Za ten przypadek odpowiada oczywiście ten fragment kodu:
22 23 24 |
/* Warning */ $zero = 0; $dzielenie = 8 / $zero; |
Jak to poprawić? Oczywiście w naszym wypadku wystarczy podstawić inną wartość do zmiennej, ale to nie jest rozwiązanie w prawdziwym świecie. W prawdziwym świecie musimy: Po pierwsze, zastanowić się, czy wynik 0 jest w ogóle możliwy. Na przykład gdy liczymy pole powierzchni jakiejś figury geometrycznej. O ile nie jest to punkt, to powinien mieć jakąś powierzchnię, choćby najmniejszą. Więc na etapie zwracania wyniku, użytkownik (lub aplikacja) powinna się dowiedzieć, że coś jest nie tak, skoro wynikiem jest zero. A jeżeli zero jest możliwym wynikiem, musimy obsłużyć ten warunek przy dzieleniu. Ponieważ pierwszy przypadek wychodzi znacznie poza nasz artykuł, zrobimy to na sposób numer dwa:
22 23 24 25 26 27 28 |
/* Warning */ $zero = 0; if (0 !== $zero) { $dzielenie = 8 / $zero; } else { echo PHP_EOL . 'Nie można podzielić przez zero, tutaj robimy coś innego!' . PHP_EOL; } |
Nadal zobaczymy komunikat, ale nie zobaczymy błędu. To nasz komunikat i możemy z tym fantem zrobić cokolwiek zechcemy.
No, to włączamy naszą aplikację I cóż się pokazuje?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Test przy wersji 7.4.4 Array ( [0] => ananasy [1] => żółte [2] => zielone ) <br /> <b>Notice</b>: Undefined variable: liczba_przykladowa in <b>C:\bin\domeny\test.local\public_html\test_error_reporting.php</b> on line <b>16</b><br /> NULL <br /> <b>Deprecated</b>: Invalid characters passed for attempted conversion, these have been ignored in <b>C:\bin\domeny\test.local\public_html\test_error_reporting.php</b> on line <b>20</b><br /> 101000110111 Nie można podzielić przez zero, tutaj robimy coś innego! KONIEC |
Tak, jak się spodziewaliśmy. Nie ma już błędu, tylko nasz komunikat o tym, że nie można dzielić przez zero. Ale nadal widzimy dwa błędy. Notice oraz Deprecated. Co jest groźniejsze? Moim zdaniem Deprecated. Oznacza on, że dana konstrukcja w kolejnej wersji PHP może być usunięta i nasz kod po prostu przestanie działać. W najlepszym razie da nam ostrzeżenie. Warto przeczytać co w danym kontekście oznacza ten komunikat. Kiedy usuwano funkcje mysql_*, długo pozostawały w statusie Deprecated. Na tyle długo, że uśpiło to czujność developerów, którzy albo przestawali zwracać na to uwagę, albo nawet nie widzieli komunikatów tego typu. Aż przyszedł pewien piękny dzień, gdy nadeszło PHP7 i te funkcje przestały działać. A byłe deprecated od wersji „5.5.0”, naprawdę, było dużo czasu na zmianę. Szczególnie, że ta akurat nie była zbyt trudna, należało użyć mysqli_*. Oczywiście nie jeden do jednego, ale to było stosunkowo proste. Czemu tyle stron się posypało… przez maskowanie tego rodzaju komunikatów.
Co jest nie tak u nas? Odpowiada za to ten fragment:
18 19 20 |
/* Deprecated */ $liczba_szesnastkowa = 'za37'; echo base_convert($liczba_szesnastkowa, 16, 2); |
Konwertujemy tutaj liczbę szesnastkową za37 na liczbę dwójkową. Tylko właśnie… „z” nie jest znakiem liczby szesnastkowej. Te znaki to 0-9 i a-f. W teorii możemy sobie wyobrazić, że ktoś wpisał „z” zamiast „x”, którym można oznaczać liczby szesnastkowe. Do wersji 7.3, PHP po prostu ignorował znaki spoza zakresu i konwertował resztę. W wersji 7.4 robi to samo, ale wysyłam nam informację, że jest to zachowanie przestarzałe. W nowszej wersji PHP, w wersji 8, ta informacja zostanie zamieniona w inny rodzaj błędu. I może się okazać, że aplikacja przestaje działać. Jak to poprawić? Ano, należy sprawdzić, czy przekazywany łańcuch jest na pewno liczbą szesnastkową. PHP zapewnia nam fajną funkcję do tego, ctype_xdigit. Nasz kod może wyglądać tak:
18 19 20 21 22 23 24 |
/* Deprecated */ $liczba_szesnastkowa = 'za37'; if ( ctype_xdigit( $liczba_szesnastkowa ) ) { echo base_convert($liczba_szesnastkowa, 16, 2); } else { echo PHP_EOL . 'To nie jest liczba szesnastkowa!' . PHP_EOL; } |
I teraz zamiast informacji o przestarzałym zachowaniu, dostaniemy jasny komunikat, że wprowadzona liczba nie jest liczbą szesnastkową. I możemy coś z tym zrobić, wiedząc o tym, a nie iść na żywioł i liczyć na to, że jakoś to będzie.
Po uruchomieniu naszego kodu, tym razem zobaczymy ostatni błąd:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Test przy wersji 7.4.4 Array ( [0] => ananasy [1] => żółte [2] => zielone ) <br /> <b>Notice</b>: Undefined variable: liczba_przykladowa in <b>C:\bin\domeny\test.local\public_html\test_error_reporting.php</b> on line <b>16</b><br /> NULL To nie jest liczba szesnastkowa! Nie można podzielić przez zero, tutaj robimy coś innego! KONIEC |
I świetnie! W linii 16 używamy zmiennej, która nie została wcześniej zdefiniowana. To jest jasne. A dlaczego jest to ważne? Ot, choćby z powodu literówek. Możemy sobie wyobrazić taki kod:
1 2 3 4 5 6 7 |
function podajWynik() :int { return 153; } $wynik = podajWynik(); $licz = $wynik * 100; echo 'Stukrotność to ' . $lycz; |
Ten kod nam nie zadziała, ponieważ zrobiliśmy literówkę. Użyliśmy zmiennej $lycz zamiast $licz. PHP poinformuje nas, że jest to zmienna niezadeklarowana, a więc NULL. A to nie jest wynik pomnożony przez 100. Może też się okazać, że ktoś nie wypełnił formularza właściwie i nie mamy w zmiennej $_GET czy $_POST tego, czego oczekujemy. Takie rzeczy należy sprawdzać. Tutaj zależność to kod źródłowy, więc poprawka wygląda tak:
15 16 17 |
/* Notice */ $liczba_przykladowa = 5; var_dump($liczba_przykladowa); |
I już nie mamy ostrzeżenia, bo wcześniej zadeklarowaliśmy zmienną. Usunąłem komentarze, które wskazywały, gdzie będą się pojawiać błędy (bo już się nie pojawiają) i teraz całość naszego kodu wygląda tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<?php error_reporting(E_ALL); ini_set('display_errors', 1); echo 'Test przy wersji ' . PHP_VERSION . PHP_EOL; $banany = ['żółte', 'zielone']; $owoce = ['ananasy', ...$banany]; print_r($owoce); $liczba_przykladowa = 5; var_dump($liczba_przykladowa); $liczba_szesnastkowa = 'za37'; if (ctype_xdigit($liczba_szesnastkowa)) { echo base_convert($liczba_szesnastkowa, 16, 2); } else { echo PHP_EOL . 'To nie jest liczba szesnastkowa!' . PHP_EOL; } $zero = 0; if (0 !== $zero) { $dzielenie = 8 / $zero; } else { echo PHP_EOL . 'Nie można podzielić przez zero, tutaj robimy coś innego!' . PHP_EOL; } class TestLiczby { public int $liczba; } $testLiczby = new TestLiczby(); $testLiczby->liczba = 1; echo PHP_EOL . 'KONIEC'; |
A wynik działania wygląda tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Test przy wersji 7.4.4 Array ( [0] => ananasy [1] => żółte [2] => zielone ) int(5) To nie jest liczba szesnastkowa! Nie można podzielić przez zero, tutaj robimy coś innego! KONIEC |
Kod jest oczywiście bezsensowny, ale usunęliśmy z niego błędy czterech rodzajów. Dbajcie o swój kod, wyświetlajcie komunikaty. Pamiętajcie proste zasady:
Co z błędami: | Rodzaj serwera | ||
---|---|---|---|
Development | Staging | Live | |
Wyświetlanie | TAK | TAK | NIE |
Logowanie | TAK | TAK | TAK |