Debugowanie aplikacji jest podstawowym działaniem podejmowanym, gdy coś nie działa. Niezależnie od tego, czy używamy echo (‘d…a’), die (‘nie działa’) czy profesjonalnych narzędzi (nie żeby echo było mało profesjonalne 😉 ) , robimy tak naprawdę to samo – śledzimy sposób działania aplikacji w danym momencie, aby zrozumieć, co się dzieje z danymi.

Metoda “die” jest szczególnie przydatna, aby stwierdzić czy w ogóle kod, który widzimy jest tym, który działa na serwerze i tym który w danym momencie chcemy zbadać. Zazwyczaj to pierwsze co robię, bo zdarzyło mi się już zrobić poprawkę i dziwić się, czemu nie pomogła, tymczasem pracowałem na złym katalogu.

Muscula - narzędie do debugowania

Muscula – nowe narzędzie do debugowania dla programistów

Czasami to, że nie widzimy błędu, nie oznacza, że on nie istnieje. Zdarzało mi się pracować nad aplikacjami, gdzie wyświetlanie ostrzeżeń było wyłączane na tak wielu poziomach, że praktycznie uniemożliwiało to sprawdzenie, co jest nie tak. Wtedy właściwie musimy odpalać debuggera i krok po kroku sprawdzać, co się dzieje, bo nie można polegać na logach i komunikatach.

Jedną z moich ulubionych metod rozwiązywania problemów jest redukowanie kodu i “psucie bardziej”. Bierzemy na warsztat fragment kodu, który stanowi problem i usuwamy z niego coraz bardziej zbędne części, jednocześnie obserwując zmiany. Redukujemy ten kod do takiego fragmentu, który zostawia nam widoczny tylko element problematyczny i dopiero wtedy staramy się znaleźć rozwiązanie. W moim doświadczeniu jest to metoda bardzo skuteczna, dużo lepsza od patrzenia się na kod i próbowanie wymyślenia rozwiązania.

 

Wyświetlanie błędów

Domyślnie wszystkie błędy PHP nie są wyświetlane, ponieważ mogłoby to doprowadzić do wycieku informacji wrażliwych wskazujących na to, jak zbudowana jest nasza aplikacja. Jednakże w środowisku developerskim warto  włączyć te komunikaty, aby wiedzieć o błędach bez potrzeby zaglądania do logów. W tym celu do kodu aplikacji dodaj:

<?php 
ini_set("display_errors",1);
error_reporting(E_ALL);
//code goes here
?>

Gdy korzystasz z frameworku (Zend, Symphony), domyślnie ta opcja jest włączona w trybie developerskim.

 

Podstawowe metody wyświetlania danych

Moją ulubioną metodą na szybkie sprawdzenie co się dzieje jest die($zmienna), pozwala to szybko ocenić jakie dane trafiły do zmiennej, jednakże jest to pomocne tylko w szybkich testach i prostych przypadkach. Gdy masz złożone struktury danych pomocne są inne metody:

  • print_r($zmienna)
  • var_dump($zmienna)

Dodatkowo, gdy chcesz zebrać więcej informacji o zmiennej lub miejscu, w którym dochodzi do problemu, warto przypatrzeć się tym metodom:

  • get_defined_vars(); – pobiera listę zmiennych zadeklarowanych w danym miejscu; przydaje się, gdy chcesz dorobić funkcjonalność do aplikacji i dowiedzieć się z czego w danym miejscu można skorzystać;
  • debug_zval_dump(); pobiera zmienną i liczbę referencji do niej; pomaga ocenić, gdzie ta zmienna jest jeszcze wykorzystywana,
  • debug_print_backtrace(); wyświetla całą ścieżkę wywołania do danego miejsca; pozwala znaleźć, co wywołało to miejsce w kodzie.

Poniżej widać na przykładzie, jak te funkcje działają:

var_dump($someObj)

object(stdClass)#1 (2) {
  ["car"]=>
  string(3) "suv"
  ["engine"]=>
  string(2) "v8"
}






print_r($someObj);

stdClass Object
(
    [car] => suv
    [engine] => v8
)






print_r(get_defined_vars());

Array
(
    [_GET] => Array
        (
        )

    [_POST] => Array
        (
        )

    [_COOKIE] => Array
        (
        )

    [_FILES] => Array
        (
        )

    [argv] => Array
        (
            [0] => /home/q/Projects/muscula/Muscula2Loggers/muscula-php-logger/dsadas.php
        )

    [argc] => 1
    [_SERVER] => Array
        (
            [PATH] => /usr/local/bin:/usr/sbin:/usr/
            [DOCUMENT_ROOT] =>
            [REQUEST_TIME_FLOAT] => 1635255534.3531
            [REQUEST_TIME] => 1635255534

        )

    [someObj] => stdClass Object
        (
            [car] => suv
            [engine] => v8
        )

)

debug_zval_dump($someObj);

object(stdClass)#1 (2) refcount(2){
  ["car"]=>
  string(3) "suv" refcount(1)
  ["engine"]=>
  string(2) "v8" refcount(1)
}

debug_print_backtrace();

 

Debugowanie za pomocą IDE + XDebug

Jest to najbardziej efektywny sposób debugowania. Pozwala ustalać breakpointy (miejsce zatrzymania kodu), abyśmy mogli przeglądać, co się dzieje z danymi w danym miejscu. Jednocześnie umożliwia ewaluowanie wyrażenia, np. sprawdzić, co się stanie, gdy zmienimy plus na minus, albo ile wynosi suma jakichś dwóch zmiennych. Nie ma potrzeby w tym celu zmieniać kodu.

Niezależnie od tego z jakiego IDE korzystasz, potrzebny Ci będzie XDebug.
Jego instalacja jest inna w zależności od systemu operacyjnego:

  • W przypadku system Linux jest to proste. Wykonujemy polecenie
    sudo apt install php-xdebug.
  • W przypadku systemu Windows należy zainstalować wersję Debug Pack lub ręcznie doinstalować rozszerzenie.

Gdy już masz wszystko gotowe, możesz przejść do pracy.

PHP Storm:

Wybieramy z menu Run -> Edit Configurations

W wyświetlonym oknie naciśnij przycisk plus (Add new configuration) a następnie wybierz z listy “PHP Web Page”

W oknie konfiguracji wybierz serwer, na którym działa aplikacja (lokalny Nginx lub Apache).

Po naciśnięciu “Apply” i “OK” odpal debugowanie ikonką robaka na pasku narzędzi.

Następnie możesz oznaczyć breakpoint czerwoną kropką i aplikacja zatrzyma się w wybranym miejscu.

DEBUGOWANIE WordPress

W celu wyświetlania błędów w WordPress najprościej jest włączyć tryb WP_DEBUG. Robimy to zmieniając plik wp-config.php i dodając linię na początku.

Ważne: Nigdy nie powinno się włączać tego trybu na produkcji.

Warto jednak zdawać sobie sprawę, że wyświetlanie błędów w tym trybie niesie ze sobą sporo niedogodności. Nie można liczyć np. na wyświetlanie bezpośrednio błędów z wywołań asynchronicznych, czasami całkowicie uniemożliwiając korzystanie ze strony www lub jej niektórych funkcji. Na szczęście są na to lepsze sposoby.

Jeśli chcesz wysyłać wszystkie komunikaty typu debug do logu, należy włączyć opcję:
define( 'WP_DEBUG_LOG’, true);
Spowoduje to, że wszystkie te komunikaty będą logowały w pliku Debug.log

Możesz też podać nazwę konkretnego pliku:
define( 'WP_DEBUG_LOG’, '/logs/wp-errors.log’ );

Sterować wyświetlaniem komunikatów możesz również za pomocą ustawienia
define ( 'WP_DEBUG_DISPLAY’, true/false);

 

PHP Console

https://github.com/barbushin/php-console

Projekt ten pozwala wyświetlać błędy PHP w konsoli przeglądarki. Niesie to ze sobą mnóstwo zalet:
Wiesz o błędzie niezależnie gdzie on wystąpił
Możesz przeglądać wartości zmiennej bez wyświetlania ich na stronie
Ładnie formatuje zmienne

Instalacja jest dosyć prosta. Pobierz bibliotekę PHP Console, wrzuć ją do katalogu WordPress lub jakiejkolwiek innej strony czy aplikacji i dodaj fragment kodu:

$handler = PhpConsole\Handler::getInstance();
$handler->start();

Następnie należy zainstalować do przeglądarki Chrome rozszerzenie PHP Console i można startować.

Niestety projekt jest od dłuższego czasu mało rozwijany, więc trzeba się spodziewać, że przy nowszych projektach może być problem z jego uruchomieniem.

Logowanie i debugowanie z Muscula

Muscula to system służący do logowania i analizy błędów. Po dodaniu fragmentu kodu do aplikacji pozwala w przejrzysztym interfejsie przeglądać wszystkie błędy, które w niej wystąpiły, a także debugować nawet na produkcji.

Integracja jest bardzo prosta. Wystarczy założyć konto na Muscula, następnie dodać nowy projekt i log. Po czym za pomocą composera zainstalować bibliotekę:

composer require muscula/muscula-php-logger (jeśli nie używamy composera po prostu pobieramy ją z gitlaba)

Następnie należy dodać fragment kodu, który został nam wyświetlany po dodaniu logu.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
 
<?php namespace Muscula\Test;

use Muscula\Handler;

define('Muscula\Test\BASE_DIR', realpath(__DIR__ . '/..'));
define('Muscula\Test\TMP_DIR', BASE_DIR . '/build');

if(!is_dir(TMP_DIR)) {
    mkdir(TMP_DIR);
}

require_once BASE_DIR . "/vendor/autoload.php";
require_once BASE_DIR. '/src/Muscula/Handler.php';

class_exists('Muscula\Connector');

$handler = Handler::getInstance();
$handler->start('<LOG_ID>');
$handler = Handler::getInstance();
$handler->start(‘<ID_TWOJEGO LOGU>');

Jeśli chcesz debugować wartość jakiejś zmiennej na produkcji, możesz skorzystać z funkcji debug:

 

Zaletą tego rozwiązania jest to, że oprócz logowania błędów backendowych można dodać także drugi log, który będzie monitorował błędy powstałe w przeglądarce, na każdym urządzeniu użytkownika. Po dodaniu logu zostanie ponownie wyświetlony fragment kodu JavaScript, który należy wkleić w nagłówek strony.

Logowanie i debugowanie WordPress z Muscula

Z systemu Muscula można także skorzystać w WordPressie. W tym celu możesz dodać kod podobnie jak powyżej dla każdej strony www napisanej w PHP. Możesz też zainstalować dedykowną wtyczkę o nazwie Muscula (menu Ustawienia -> Wtyczki -> Dodaj nową). Po instalacji wtyczkę należy skonfigurować. W tym celu wprowadź LOG_ID na ekranie konfiguracji.

Podsumowanie

Jest wiele sposobów na analizę błędów. Wybierz taki, który oszczędzi Ci najwięcej czasu. Strony WWW czy aplikacje napisane w PHP potrafią bardzo sprawnie działać, o ile zadbamy o to, aby wiedzieć o problemach. Sprawdzanie wszystkiego we własnym środowisku nie jest zawsze tym samym, co praca na produkcji. Warto więc używać dodatkowych narzędzi, które usprawniają naszą pracę, zwłaszcza gdy są dostępne za darmo.