Pull to refresh

Удобная отладка с PHPixie Debug

Reading time5 min
Views9.4K
image
PHPixie Debug был создан чтобы улучшить отладку при разработке в любой среде. Конечно если вы уже используете веб фреймворк то скорее всего проблем с отладкой нет, но вот когда вы пишете какую-то библиотеку, решаете задачку или даже работаете с Wordpress, то удобной отладки сильно недостает. Даже для такого базового функционала как превратить все ошибки в исключения приходится регистрировать свой хендлер. В таких случаях PHPixie Debug в всего лишь две строки кода создаст удобную среду для разработки.

Исключения и трейсы


Debug предоставляет в консоли то удобство работы с исключениями к которому мы уже привыкли в веб фреймворках. При написании библиотек мне очень не хватало красивых информативных трейсов c выводом той части кода в которой произошло исключение. Большая проблема трассирования в PHP в том что если просто вызвать print_r(debug_backtrace()) и одним из аргументов какого-либо вызова являлся объект то результат превратится в гору текста. Есть конечно debug_print_backtrace(), но во-первых массивы он все равно выводит полностью, во-вторых чтобы получить его в виде строки приходится использовать буфер. А вот как обработает трейс исключения PHPixie Debug:

<?php
require_once('vendor/autoload.php');
$debug = new \PHPixie\Debug();

try{
    throw new \Exception("test");
    
}catch(\Exception $e) {
    //Вывод исключения
    $debug->exceptionMessage($e);
}

echo "\n-------\n";

//Автоматический вывод исключений
//Также при исключении будет выведен весь лог
//(о нем речь пойдет позже)
$debug->registerHandlers();

class Test
{
    public function a($string)
    {
        $array = array(1, 2);
        $this->b($string, $array);
    }
    
    public function b($string, $array)
    {
        $object = (object) array('t' => 1);
        $this->c($string, $array, $object);
    }
    
    public function c()
    {
        substr();
    }
}

$test = new Test();
$test->a("pixie");


Exception: test                                                       
                                                                      
5                                  
6 try{                                                                 
>     throw new \Exception("test");                                    
8                                                                      
9 }catch(\Exception $e) {                                              
                                                                      
#0 D:\debug\examples\exceptions.php:7                                
                                                                      
-------                                                               
                                                                                                                                       
ErrorException: substr() expects at least 2 parameters, 0 given       
                                                                      
36     public function c()                                             
37     {                                                               
>>         substr();                                                   
39     }                                                               
40 }                                                                   
                                                                      
#0 D:\debug\examples\exceptions.php:38                               
#1 D:\debug\examples\exceptions.php:38                               
    substr()                                                          
#2 D:\debug\examples\exceptions.php:33                               
    Test->c('pixie', array[2], stdClass)                              
#3 D:\debug\examples\exceptions.php:27                               
    Test->b('pixie', array[2])                                        
#4 D:\debug\examples\exceptions.php:43                               
    Test->a('pixie')                                                  
                                                                      
Logged items:                                                                                                                              

Кстати обратите внимание что в трейсе не видно хендлера который превратил PHP ошибку в исключение, много других библиотек часто забывают его спрятать тем самым засоряя трейс. PHPixie прячет все такие вмешательства в стек вызова.

Вывод переменных


Вывод сделан через статическую функцию \PHPixie\Debug::dump(), это кстати первая статическая функция в PHPixie. Причина этому то, что по замыслу функции отладки не являются частью вашего приложения и вы и так удалите их как только все заработает. Поэтому нет смысла передавать класс Debug как зависимость через конструктор. Тут кстати стоит отметить что эти функции будут работать только если сам объект Debug уже был создан, таким образом они всего лишь прокси и ни какой статической логики в PHPixie никогда не будет.

<?php
require_once('vendor/autoload.php');

use PHPixie\Debug;
$debug = new Debug();

Debug::dump("Array dump:");
Debug::dump(array(1));

Debug::dump("Short array dump:");
//Короткий дамп выводит минимум информации. 
//Это удобно например для вывода количества
//элементов массива или имя класса объекта
Debug::dump(array(1), true);

$object = (object) array('t' => 1);
Debug::dump("Object dump:");
Debug::dump($object);

Debug::dump("Short object dump:");
Debug::dump($object, true);

Debug::dump("Dump trace with parameters");
class Test
{
    public function a($string)
    {
        $array = array(1, 2);
        $this->b($string, $array);
    }
    
    public function b($string, $array)
    {
        $object = (object) array('t' => 1);
        $this->c($string, $array, $object);
    }
    
    public function c()
    {
        Debug::trace();
    }
}

$t = new Test();
$t->a("test");


'Array dump:'

Array
(
    [0] => 1
)


'Short array dump:'

array[1]

'Object dump:'

stdClass Object
(
    [t] => 1
)


'Short object dump:'

stdClass

'Dump trace with parameters'

#0 D:\debug\examples\dumping.php:37
    PHPixie\Debug::trace()
#1 D:\debug\examples\dumping.php:32
    Test->c('test', array[2], stdClass)
#2 D:\debug\examples\dumping.php:26
    Test->b('test', array[2])
#3 D:\debug\examples\dumping.php:42
    Test->a('test')


Лог


Для того чтобы разделить сообщения отладки от вывода самой программы часто сообщения записывают в массив который выводят в конце исполнения программы. Единственная проблема в том, что если возникает ошибка или где-то используется exit() то после этого сообщения уже не выведутся. PHPixie Debug выводит лог при исключениях и может также зарегистрировать хендлер для обязательного вывода лога сообщений по завершении работы скрипта. Вот два примера:

use PHPixie\Debug;
$debug = new Debug();

Debug::log("test");
Debug::log(array(3));

class Test
{
    public function a($string, $num)
    {
        Debug::logTrace();
    }
}
$t = new Test();
$t->a("test", 5);

//Ручной вывод сообщений
$debug->dumpLog();


Logged items:

[0] D:\debug\examples\logging.php:7
'test'

[1] D:\debug\examples\logging.php:8
Array
(
    [0] => 3
)


[2] D:\debug\examples\logging.php:16
#0 D:\debug\examples\logging.php:16
    PHPixie\Debug::logTrace()
#1 D:\debug\examples\logging.php:20
    Test->a('test', 5)


И с автоматическим выводом:

<?php

use PHPixie\Debug;
$debug = new Debug();

//Передав 'true' при регистрации хендлеров
//мы также включаем вывод лога в конце
//исполнения
$debug->registerHandlers(true);

Debug::log("test");

echo("Logged messages will be printed below");


Logged messages will be printed now

Logged items:

#0 D:\debug\examples\log_handler.php:13
'test'


В заключение


Главной целью библиотеки является не сам вывод трейсов и лога, а скорее удобное представление их в виде классов, что позволит в будущем построит веб версию дебага для PHPixie, ведь фактически осталось только добавить красивый темплейт для рендеринга. Но главное преимущество Debug как самостоятельного инструмента в том, что всего в две строчки дополнительного кода можно получить удобную среду для разработки не веб приложений. Надеюсь в следующий раз когда работодатель предложит вам решить задачку про коммивояжера или вам понадобится трассировка в Wordpress, вы вспомните эту библиотеку и сэкономите время какое потратили бы на debug_backtrace().

Демо


Чтобы попробовать Debug своими руками достаточно:

git clone https://github.com/phpixie/debug
cd debug/examples
 
#если у вас еще нет Композера
curl -sS https://getcomposer.org/installer | php
 
php composer.phar install
php exceptions.php
php logging.php
php log_handler.php
php dumping.php


И кстати как и у всех других библиотеках от PHPixie вас ждет 100% покрытие кода тестами и работа под любой версией PHP старше 5.3 (включая новую 7 и HHVM).
Tags:
Hubs:
+7
Comments15

Articles