可以在php中获取调用方上下文的神奇常量吗?

可以在php中获取调用方上下文的神奇常量吗?,php,constants,Php,Constants,我想创建一个调试函数,它转储有关执行上下文的信息以及一些其他信息 在debug.php中,我有一个函数,可以转储作为参数传递的任何内容。我感兴趣的是如何从example.php调用dump函数,并让它返回调用上下文的文件名、行号和函数名 1. <?php 2. function my_function(){ 3. $var = 'My example'; 4. dump( $var ); 5. } 6. ?> 1。 example.php 我希望上面的函数输出:“exam

我想创建一个调试函数,它转储有关执行上下文的信息以及一些其他信息

在debug.php中,我有一个函数,可以转储作为参数传递的任何内容。我感兴趣的是如何从example.php调用dump函数,并让它返回调用上下文的文件名、行号和函数名

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

我希望上面的函数输出:“example.php,my_函数,4:my example”

是否有这样做的方法(除了将
\uuuuuuu文件
\uuuu函数
\uuuu行
)作为参数传递?

backtrace的输出是一个关联数组的数组,这些数组命名您要查找的常量。对于,数组
debug\u backtrace()
返回的结果如下所示:

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

        )

)
是的,你可以用

它返回一个包含所有调用者和文件(也跟踪包含的文件)的数组,顺序相反(最高的祖先最后一个)。因此调用者将是数组中的第一个:

$caller_info = next(debug_backtrace());

我也使用debug_backtrace,我尝试处理不同的场景,这可能看起来太耗时或者是个坏主意,但对我来说(构建自己的小型mvc非常有用)。要处理的场景示例:

  • __我的类的析构函数在退出调用方上下文时被自动调用
  • 类的方法/析构函数自动调用,因为已声明为会话处理程序
  • 我的方法/函数是从全局上下文(而不是从其他函数/方法)调用的
  • 等等
所有这些场景都会影响debug_backtrace带来的结果,我的debug函数(定义如下)会尝试处理这些场景

每个函数/方法的定义如下

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)的行将无法打印(例如,打印命令放在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>";
        }
    }
}
$tr(trace)数组包含调试回溯的结果,因为它们存在于被调用方faunction中。还有一件事要提的是,在成为呼叫者之前,呼叫者总是被呼叫者

这些是$dbg_log数组的输出(在致命错误或正常退出时)给出的一些真实结果(对您来说没有意义,但是提供的全部信息是显而易见的):

对于您定义的每个函数/方法,都有很多信息、行号、类等,只需很少的努力(只需使用这个
函数my_func(){if(u调试){dbg(DEBUG_backtrace(),u class_u);}

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>";
        }
    }
}
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;
}
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