php:确定函数从何处调用

时间:2021-07-16 07:18:26

is there a way to find out, where a function in PHP was called from? example:

有没有一种方法可以找到,PHP中的函数是从哪里调用的?例子:

function epic()
{
  fail();
}

function fail()
{
  //at this point, how do i know, that epic() has called this function?
}

8 个解决方案

#1


113  

You can use debug_backtrace().

您可以使用debug_backtrace()。

Example:

例子:

<?php

function epic( $a, $b )
{
    fail( $a . ' ' . $b );
}

function fail( $string )
{
    $backtrace = debug_backtrace();

    print_r( $backtrace );
}

epic( 'Hello', 'World' );

Output:

输出:

Array
(
    [0] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 5
            [function] => fail
            [args] => Array
                (
                    [0] => Hello World
                )

        )

    [1] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 15
            [function] => epic
            [args] => Array
                (
                    [0] => Hello
                    [1] => World
                )

        )

)

#2


22  

Use debug_backtrace():

使用debug_backtrace():

function fail()
{
    $backtrace = debug_backtrace();

    // Here, $backtrace[0] points to fail(), so we'll look in $backtrace[1] instead
    if (isset($backtrace[1]['function']) && $backtrace[1]['function'] == 'epic')
    {
        // Called by epic()...
    }
}

#3


14  

So if you still REALLY don't know how, than here is solution:

所以如果你还是不知道怎么做,这里有一个解决方案:

$backtrace = debug_backtrace();
echo 'Mu name is '.$backtrace[1]['function'].', and I have called him! Muahahah!';

#4


14  

Fastest and simplest solution as I found

我找到了最快最简单的解决方案

public function func() { //function whose call file you want to find
    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}

$trace: Array
(
    [0] => Array
        (
            [file] => C:\wamp\www\index.php
            [line] => 56
            [function] => func
            [class] => (func Class namespace)
            [type] => ->
        )

)

I test the speed on Lenovo laptop: Intel Pentiom CPU N3530 2.16GHz, RAM 8GB

我在联想笔记本电脑上测试了速度:Intel Pentiom CPU N3530 2.16GHz, RAM 8GB

global $times;
$start = microtime(true);
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$times[] = microtime(true) - $start;

Results:

结果:

count($times):  97
min:    2.6941299438477E-5
max:   10.68115234375E-5
avg:    3.3095939872191E-5
median: 3.0517578125E-5
sum:  321.03061676025E-5

the same results with notation without E-5
count($times):  97
min:    0.000026941299438477
max:    0.0001068115234375
avg:    0.000033095939872191
median: 0.000030517578125
sum:    0.0032103061676025

#5


5  

Use the debug_backtrace function: http://php.net/manual/en/function.debug-backtrace.php

使用debug_backtrace函数:http://php.net/manual/en/function.debug-backtrace.php

#6


3  

Try below code.

试试下面的代码。

foreach(debug_backtrace() as $t) {              
   echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()<br/>";
}

#7


1  

If you want to trace the exact origin of the call at the top of the stack you can use the following code:

如果您想要跟踪栈顶调用的确切起源,可以使用以下代码:

$call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

This will ignore chained functions and get only the most relevant call info (relevant is used loosely as it depends what your are trying to accomplish).

这将忽略链锁函数,只获取最相关的调用信息(相关的使用是松散的,因为这取决于您要完成的任务)。

#8


-1  

function findFunction($function, $inputDirectory=""){
    //version 0.1
    $docRoot = getenv("DOCUMENT_ROOT");
    $folderArray = null;
    $dirArray = null;

    // open directory
    $directory = opendir($docRoot.$inputDirectory);

    // get each entry
    while($entryName = readdir($directory)) {
        if(is_dir($entryName) && $entryName != "." && $entryName != ".."){
            $folderArray[] = str_replace($inputDirectory, "", $entryName);
        }
        $ext = explode(".", $entryName);
        if(!empty($ext[1])){
            $dirArray[] = $docRoot.$inputDirectory."/".$entryName;
        }
    }

    // close directory
    closedir($directory);
    $found = false;

    if(is_array($dirArray)){
        foreach($dirArray as $current){
            $myFile = file_get_contents($current);
            $myFile = str_replace("<?php", "", $myFile);
            $myFile = str_replace("?>", "", $myFile);
            if(preg_match("/function ".$function."/", $myFile)){
                $found = true;
                $foundLocation = $current;
                break;
            }
        }
    }
    if($found){
        echo $foundLocation;
        exit;
    } else if(is_array($folderArray)){
        foreach($folderArray as $folder){
            if(!isset($return)){
                $return = findFunction($function, $inputDirectory."/".$folder);
            } else if($return == false){
                $return = findFunction($function, $inputDirectory."/".$folder);
            }
        }
    } else {
        return false;
    }
}

findFunction("testFunction", "rootDirectory");

Hope it helps somebody. If the actual function is outside httpdocs then it can not be found because the server will be setup to not allow it. Only tested it one folder deep too but the recursive methodology should work in theory.

希望它能帮助别人。如果实际的函数在httpdocs之外,那么就无法找到它,因为服务器将设置为不允许它。只对一个文件夹进行了深入的测试,但是递归方法在理论上应该是有效的。

This is like version 0.1 but I don't intend on continuing development on it so if someone updates it feel free to repost it.

这就像0。1版本,但是我不打算继续开发它,所以如果有人更新它,可以随意重新发布。

#1


113  

You can use debug_backtrace().

您可以使用debug_backtrace()。

Example:

例子:

<?php

function epic( $a, $b )
{
    fail( $a . ' ' . $b );
}

function fail( $string )
{
    $backtrace = debug_backtrace();

    print_r( $backtrace );
}

epic( 'Hello', 'World' );

Output:

输出:

Array
(
    [0] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 5
            [function] => fail
            [args] => Array
                (
                    [0] => Hello World
                )

        )

    [1] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 15
            [function] => epic
            [args] => Array
                (
                    [0] => Hello
                    [1] => World
                )

        )

)

#2


22  

Use debug_backtrace():

使用debug_backtrace():

function fail()
{
    $backtrace = debug_backtrace();

    // Here, $backtrace[0] points to fail(), so we'll look in $backtrace[1] instead
    if (isset($backtrace[1]['function']) && $backtrace[1]['function'] == 'epic')
    {
        // Called by epic()...
    }
}

#3


14  

So if you still REALLY don't know how, than here is solution:

所以如果你还是不知道怎么做,这里有一个解决方案:

$backtrace = debug_backtrace();
echo 'Mu name is '.$backtrace[1]['function'].', and I have called him! Muahahah!';

#4


14  

Fastest and simplest solution as I found

我找到了最快最简单的解决方案

public function func() { //function whose call file you want to find
    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}

$trace: Array
(
    [0] => Array
        (
            [file] => C:\wamp\www\index.php
            [line] => 56
            [function] => func
            [class] => (func Class namespace)
            [type] => ->
        )

)

I test the speed on Lenovo laptop: Intel Pentiom CPU N3530 2.16GHz, RAM 8GB

我在联想笔记本电脑上测试了速度:Intel Pentiom CPU N3530 2.16GHz, RAM 8GB

global $times;
$start = microtime(true);
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$times[] = microtime(true) - $start;

Results:

结果:

count($times):  97
min:    2.6941299438477E-5
max:   10.68115234375E-5
avg:    3.3095939872191E-5
median: 3.0517578125E-5
sum:  321.03061676025E-5

the same results with notation without E-5
count($times):  97
min:    0.000026941299438477
max:    0.0001068115234375
avg:    0.000033095939872191
median: 0.000030517578125
sum:    0.0032103061676025

#5


5  

Use the debug_backtrace function: http://php.net/manual/en/function.debug-backtrace.php

使用debug_backtrace函数:http://php.net/manual/en/function.debug-backtrace.php

#6


3  

Try below code.

试试下面的代码。

foreach(debug_backtrace() as $t) {              
   echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()<br/>";
}

#7


1  

If you want to trace the exact origin of the call at the top of the stack you can use the following code:

如果您想要跟踪栈顶调用的确切起源,可以使用以下代码:

$call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

This will ignore chained functions and get only the most relevant call info (relevant is used loosely as it depends what your are trying to accomplish).

这将忽略链锁函数,只获取最相关的调用信息(相关的使用是松散的,因为这取决于您要完成的任务)。

#8


-1  

function findFunction($function, $inputDirectory=""){
    //version 0.1
    $docRoot = getenv("DOCUMENT_ROOT");
    $folderArray = null;
    $dirArray = null;

    // open directory
    $directory = opendir($docRoot.$inputDirectory);

    // get each entry
    while($entryName = readdir($directory)) {
        if(is_dir($entryName) && $entryName != "." && $entryName != ".."){
            $folderArray[] = str_replace($inputDirectory, "", $entryName);
        }
        $ext = explode(".", $entryName);
        if(!empty($ext[1])){
            $dirArray[] = $docRoot.$inputDirectory."/".$entryName;
        }
    }

    // close directory
    closedir($directory);
    $found = false;

    if(is_array($dirArray)){
        foreach($dirArray as $current){
            $myFile = file_get_contents($current);
            $myFile = str_replace("<?php", "", $myFile);
            $myFile = str_replace("?>", "", $myFile);
            if(preg_match("/function ".$function."/", $myFile)){
                $found = true;
                $foundLocation = $current;
                break;
            }
        }
    }
    if($found){
        echo $foundLocation;
        exit;
    } else if(is_array($folderArray)){
        foreach($folderArray as $folder){
            if(!isset($return)){
                $return = findFunction($function, $inputDirectory."/".$folder);
            } else if($return == false){
                $return = findFunction($function, $inputDirectory."/".$folder);
            }
        }
    } else {
        return false;
    }
}

findFunction("testFunction", "rootDirectory");

Hope it helps somebody. If the actual function is outside httpdocs then it can not be found because the server will be setup to not allow it. Only tested it one folder deep too but the recursive methodology should work in theory.

希望它能帮助别人。如果实际的函数在httpdocs之外,那么就无法找到它,因为服务器将设置为不允许它。只对一个文件夹进行了深入的测试,但是递归方法在理论上应该是有效的。

This is like version 0.1 but I don't intend on continuing development on it so if someone updates it feel free to repost it.

这就像0。1版本,但是我不打算继续开发它,所以如果有人更新它,可以随意重新发布。