Возможно ли получить магические константы контекста вызывающего в php? - PullRequest
2 голосов
/ 20 ноября 2011

Я хотел бы создать функцию отладки, которая выводит информацию о контексте выполнения вместе с некоторой другой информацией.

В debug.php у меня есть функция, которая выводит все, что передается в качестве параметра.Меня интересует способ вызова функции dump из, скажем, example.php, чтобы она возвращала имя файла, номер строки и имя функции вызывающего контекста.

1. <?php
2. function my_function(){
3.   $var = 'My example';
4.   dump( $var );
5. }
6. ?>

example.php

Я бы хотел, чтобы вышеприведенная функция вывела: "example.php, my_function, 4: My example".

Есть ли в этом случае возможность (короткийпередачи __FILE__, __FUNCTION__ и __LINE__) в качестве параметров?

Ответы [ 3 ]

4 голосов
/ 20 ноября 2011

Да, вы можете использовать debug_backtrace().

Возвращает массив всех вызывающих и файлов (в том числе и трассируемые файлы) в обратном порядке (последний по возрасту предок). Таким образом, вызывающая сторона будет первой в массиве:

$caller_info = next(debug_backtrace());
2 голосов
/ 20 ноября 2011

PHP debug_backtrace():

print_r(debug_backtrace());

Вывод backtrace представляет собой массив ассоциативных массивов, которые называют эти константы, которые вы ищете. Для этого примера кода возвращаемый массив debug_backtrace() будет выглядеть следующим образом:

Array
(
    [0] => Array
        (
            [file] => /t.php
            [line] => 9
            [function] => abc
            [args] => Array
                (
                    [0] => a
                )

        )

)
0 голосов
/ 19 декабря 2012

Я тоже использую debug_backtrace, я пытаюсь работать с разными сценариями, это может показаться слишком трудоемким или плохой идеей, но для меня (создание моего собственного небольшого mvc было очень полезно). Пример сценариев для обработки:

  • ___ Уничтожение моего класса вызывалось автоматически при выходе из контекста вызывающего
  • метод / деструктор моего класса вызывается автоматически, потому что был объявлен обработчиком сеанса
  • мой метод / функция был вызван из глобального контекста (не из другой функции / метода)
  • и т.д ..

Все эти сценарии будут влиять на результаты, полученные debug_backtrace, моя функция отладки (описанная ниже) пытается обработать эти сценарии.

Каждая функция / метод определяется следующим образом

function my_func(){if(__DEBUG){dbg(debug_backtrace(),__CLASS__);}

затем, когда я хочу создать окончательный код, я могу запустить простой скрипт для замены этого оператора if, например

a="if(__DEBUG){dbg(debug_backtrace(),__CLASS__);}"
b="//replace_what_ever"
dir="/var/www/mydir/"

find $dir -name \*.inc -exec sed -i "s/$a/$b/g" {} \;
find $dir -name \*.php -exec sed -i "s/$a/$b/g" {} \;

Что касается функции отладки, то она может идти в самом конце скрипта, скажем, в самом и из index.php. Однако если вы определили собственный класс для обработчика сеанса, тогда самая последняя команда будет выполнена внутри деструктор этого класса.

Так что в большинстве случаев, когда что-то идет не так, ваша функция отладки сообщит вам. Однако при фатальной ошибке строка, которая печатает результаты, созданные / сохраненные (сохраненные в некотором массиве, здесь $ dbg_log) функцией отладки, не сможет печатать (например, команда print помещается в конец index.php) !! В этом случае вам нужен ручной обработчик (только для фатальных ошибок), чтобы напечатать массив результатов, вот как я это делаю:

register_shutdown_function('handleShutdown');
//Catch fatal errors
function handleShutdown() {
    $error = error_get_last();
    global $dbg_log;
    echo "<pre>";
    if(
            $error['type'] === E_COMPILE_ERROR or
            $error['type'] === E_ERROR or
            $error['type'] === E_PARSE or
            $error['type'] === E_CORE_ERROR or
            $error['type'] === E_CORE_WARNING or
            $error['type'] === E_RECOVERABLE_ERROR

    )//we need to catch fatal errors under debug
    {
        //print_r($error); if you like
        $dbg_log[] = " Tip: Start backward, the failing function (line) cannot echo a text put at the end of the function!";
        $last = count($dbg_log)-1;
        for($i=$last;$i>-1;$i--){
            echo "$i: {$dbg_log[$i]} \n<br>";
        }
    }
}

$ dbg_log используется для сбора всей этой информации, определенной в глобальном контексте (см. Ниже).

Теперь вот как выглядит моя функция отладки:

define('__DEBUG', true); // Easily switch from/to debug mode
$dbg_log = array(); // Keep log of function calling sequence for debuging purposes
 function dbg($tr, $callee_class){
     global $dbg_log;
    // If the file of the caller exists
    if(isset($tr[0]['file'])){
        $caller = $caller=$tr[0]["file"].':'.$tr[0]["line"]; // Then we can get its name and calling line
        // If the caller is a function then it was a callee before so $tr[1] should exists
        if(isset($tr[1])){
            // If the caller is a class method
            if(isset($tr[1]["class"])){
                $caller = $tr[1]["class"]."whenever->".$caller=$tr[1]["function"].':'.$caller;
            }
            // Else
            else{
                $caller = $tr[1]["function"].$caller;
            }
        }
    }
    // Else this is an auto call by php compiler
    else{
        $caller = 'auto';
    }
    // Log the debug info
    $dbg_log[] = 'Started: '.$callee_class.'::'.$tr[0]['function'].' by '.$caller;
}

Массив $ tr (trace) содержит результаты debug_backtrace в том виде, в котором они существовали внутри функции вызываемого объекта. Еще одна вещь, которую стоит упомянуть, это то, что вызывающий всегда был вызывающим, прежде чем стать вызывающим !!

Вот некоторые реальные (бессмысленные для вас, однако вся предоставленная информация очевидна) результаты, которые дает вывод массива $ dbg_log (при фатальной ошибке или нормальном выходе):

27: Started: Framework\registry::get by App\View\WebWindowOne->__construct:/var/www/MyProject/protected/view/WebWindowOne/WebWindowOne.php:36 

26: Started: App\View\WebWindowOne::__construct by Application->AppStart:/var/www/MyProject/protected/Web_Application.php:240 

25: Started: Application::AppStart by Application->__construct:/var/www/MyProject/protected/Web_Application.php:150 

24: Started: Framework\riskManager::__construct by Application->{closure}:/var/www/MyProject/protected/Web_Application.php:52 

Существует много информации, номера строки, класса и т. Д., С очень небольшим усилием (просто используя function my_func(){if(__DEBUG){dbg(debug_backtrace(),__CLASS__);}) для каждой функции / метода, который вы определяете.

...