Php get function call trace

debug_print_backtrace

debug_print_backtrace() prints a PHP backtrace. It prints the function calls, included/required files and eval() ed stuff.

Parameters

This parameter is a bitmask for the following options:

debug_print_backtrace() options
DEBUG_BACKTRACE_IGNORE_ARGS Whether or not to omit the «args» index, and thus all the function/method arguments, to save memory.

This parameter can be used to limit the number of stack frames printed. By default ( limit = 0 ) it prints all stack frames.

Return Values

Examples

Example #1 debug_print_backtrace() example

function c () debug_print_backtrace ();
>

// test.php file
// this is the file you should run

The above example will output something similar to:

#0 c() called at [/tmp/include.php:10] #1 b() called at [/tmp/include.php:6] #2 a() called at [/tmp/include.php:17] #3 include(/tmp/include.php) called at [/tmp/test.php:3]

See Also

User Contributed Notes 5 notes

Another way to manipulate and print a backtrace, without using output buffering:

// print backtrace, getting rid of repeated absolute path on each file
$e = new Exception ();
print_r ( str_replace ( ‘/path/to/code/’ , » , $e -> getTraceAsString ()));
?>

I like the output of debug_print_backtrace() but I sometimes want it as a string.

bortuzar’s solution to use output buffering is great, but I’d like to factorize that into a function. Doing that however always results in whatever function name I use appearing at the top of the stack which is redundant.

Below is my noddy (simple) solution. If you don’t care for renumbering the call stack, omit the second preg_replace().

function debug_string_backtrace () <
ob_start ();
debug_print_backtrace ();
$trace = ob_get_contents ();
ob_end_clean ();

// Remove first item from backtrace as it’s this function which
// is redundant.
$trace = preg_replace ( ‘/^#0\s+’ . __FUNCTION__ . «[^\n]*\n/» , » , $trace , 1 );

// Renumber backtrace items.
$trace = preg_replace ( ‘/^#(\d+)/me’ , ‘\’#\’ . ($1 — 1)’ , $trace );

If your show your error messages in HTML (with suitable safety using entities), this function won’t work nicely because it uses newlines for formatting.

Here is a function that works similarly, but using tags. Insert it near the beginning of your program to add a stack to Warning output only, or modify it as you like:

// Here is code for error stack output in HTML:
function error_handler_callback($errno,$message,$file,$line,$context)
if ($errno === E_WARNING)
echo «Stack, innermost first:
«.nl2br((new Exception())->getTraceAsString());
return false; // to execute the regular error handler
>
set_error_handler(«error_handler_callback»);

Here’s a function that returns a string with the same information shown in debug_print_backtrace(), with the option to exclude a certain amount of traces (by altering the $traces_to_ignore argument).

Читайте также:  Фоновое изображение с помощью HTML

I’ve done a couple of tests to ensure that it prints exactly the same information, but I might have missed something.

This solution is a nice workaround to get the debug_print_backtrace() information if you’re already using ob_start() in your PHP code.

function get_debug_print_backtrace ( $traces_to_ignore = 1 ) $traces = debug_backtrace ();
$ret = array();
foreach( $traces as $i => $call ) if ( $i < $traces_to_ignore ) continue;
>

$object = » ;
if (isset( $call [ ‘class’ ])) $object = $call [ ‘class’ ]. $call [ ‘type’ ];
if ( is_array ( $call [ ‘args’ ])) foreach ( $call [ ‘args’ ] as & $arg ) get_arg ( $arg );
>
>
>

$ret [] = ‘#’ . str_pad ( $i — $traces_to_ignore , 3 , ‘ ‘ )
. $object . $call [ ‘function’ ]. ‘(‘ . implode ( ‘, ‘ , $call [ ‘args’ ])
. ‘) called at [‘ . $call [ ‘file’ ]. ‘:’ . $call [ ‘line’ ]. ‘]’ ;
>

function get_arg (& $arg ) if ( is_object ( $arg )) $arr = (array) $arg ;
$args = array();
foreach( $arr as $key => $value ) if ( strpos ( $key , chr ( 0 )) !== false ) $key = » ; // Private variable found
>
$args [] = ‘[‘ . $key . ‘] => ‘ . get_arg ( $value );
>

$arg = get_class ( $arg ) . ‘ Object (‘ . implode ( ‘,’ , $args ). ‘)’ ;
>
>
?>

Источник

php: determine where function was called from

That definitely does what you want. But beware debug_backtrace() is an expensive call. Don’t get in the habit of using it to determine call-chains. If you want to «protect» those functions, check out OOP and protected methods.

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

global $times; $start = microtime(true); $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); $times[] = microtime(true) - $start; 
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 

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!'; 

Yes, but don’t! Not in permanent application code, anyway. Use parameters. debug_backtrace() looks like a pretty heavy operation.

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

Good and direct solution to get back trace of all the files from which particular function is called.

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).

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("", "", $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.

Читайте также:  Css by browser type

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.

Источник

How to get name of calling function/method in PHP? [duplicate]

I am aware of function debug_backtrace , but I am looking for some ready to use implementation of function like GetCallingMethodName() ? It would be perfect if it gave method’s class too (if it is indeed a method).

Ah, yet another example where a question or bug report with the superior answer or report is marked as a duplicate of an earlier though inferior posting. I’ll have to fix that problem in the industry too.

10 Answers 10

echo debug_backtrace()[1]['function']; 

As noted in the comments below, this can be further optimized by passing arguments to:

echo debug_backtrace(!DEBUG_BACKTRACE_PROVIDE_OBJECT|DEBUG_BACKTRACE_IGNORE_ARGS,2)[1]['function']; 

Just found this. Very useful BUT it’s worth noting that there could be a major overhead involved here. I ran print_r(debug_backtrace()) and it basically crashed my browser with the weight of info it returned.

If your browser crashed trying to print debug_backtrace() , you probably have other, more serious issues. Either you’re passing huge objects as parameters, or your call-stack is enormously deep, or you’re using a pretty dodgy browser!

It’s worth optimizing this a little bit: debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2)[1][‘function’]

The debug_backtrace() function is the only way to know this, if you’re lazy it’s one more reason you should code the GetCallingMethodName() yourself. Fight the laziness! 😀

«Fight the laziness! :D» But laziness is a good thing: codinghorror.com/blog/archives/000237.html :> So if someone has written such a function, I would really appreciate. :>

Who needs google while having such a great ‘programming answers search engine’ as stackoverflow users like You :> stackoverflow.com/questions/190421/caller-function-in-php-5/… Now seriously, thanks!

Читайте также:  Php mysql use result

It is not about laziness — if the programmer is paid for the solution, it is perfectly valid trying not to reinvent the wheel.

 $dbt=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2); $caller = isset($dbt[1]['function']) ? $dbt[1]['function'] : null; 

This will not waste memory as it ignores arguments and returns only the last 2 backtrace stack entries, and will not generate notices as other answers here.

Note that isset($something) ? $something : null can be shortened to $something ?? null in modern PHP versions. Edit: sorry, someone already covered this

You can also use the info provided by a php exception, it’s an elegant solution:

function GetCallingMethodName()< $e = new Exception(); $trace = $e->getTrace(); //position 0 would be the line that called this function so we ignore it $last_call = $trace[1]; print_r($last_call); > function firstCall($a, $b) < theCall($a, $b); >function theCall($a, $b) < GetCallingMethodName(); >firstCall('lucia', 'php');
Array ( [file] => /home/lufigueroa/Desktop/test.php [line] => 12 [function] => theCall [args] => Array ( [0] => lucia [1] => php ) )

Be aware, I did a quick benchmarks and looks like this solution is 2x times slower than the debug_backtrace(). However, we are talking about micro-optimization untill you dont use this method very often in your code

Yes, debug_backtrace is the right solution, but if you tend to forget the name of the functions, create an exception and print its trace might be easier to remember. In my case I use this only for code debugging, I haven’t left it on production for any reason. If I wanted to build a debugging/logging system I would use debug_backtrace.

If I call the GetCallingMethodName() function within the «theCall()», then I would expect «firstCall()» as caller function and not the function itself. Setting $last_call = $trace[2]; in GetCallingMethodName() solves the problem.

For me debug_backtrace was hitting my memory limit, and I wanted to use this in production to log and email errors as they happen.

Instead I found this solution which works brilliantly!

// Make a new exception at the point you want to trace, and trace it! $e = new Exception; var_dump($e->getTraceAsString()); // Outputs the following #2 /usr/share/php/PHPUnit/Framework/TestCase.php(626): SeriesHelperTest->setUp() #3 /usr/share/php/PHPUnit/Framework/TestResult.php(666): PHPUnit_Framework_TestCase->runBare() #4 /usr/share/php/PHPUnit/Framework/TestCase.php(576): PHPUnit_Framework_TestResult->run(Object(SeriesHelperTest)) #5 /usr/share/php/PHPUnit/Framework/TestSuite.php(757): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult)) #6 /usr/share/php/PHPUnit/Framework/TestSuite.php(733): PHPUnit_Framework_TestSuite->runTest(Object(SeriesHelperTest), Object(PHPUnit_Framework_TestResult)) #7 /usr/share/php/PHPUnit/TextUI/TestRunner.php(305): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult), false, Array, Array, false) #8 /usr/share/php/PHPUnit/TextUI/Command.php(188): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array) #9 /usr/share/php/PHPUnit/TextUI/Command.php(129): PHPUnit_TextUI_Command->run(Array, true) #10 /usr/bin/phpunit(53): PHPUnit_TextUI_Command::main() #11 " 

Источник

Оцените статью