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).
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! :D
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)
. –
Ethnarch The simplest way is:
echo debug_backtrace()[1]['function'];
As noted in the comments below, this can be further optimized by passing arguments to:
- omit both the
object
andargs
indices - limit the number of stack frames returned
echo debug_backtrace(!DEBUG_BACKTRACE_PROVIDE_OBJECT|DEBUG_BACKTRACE_IGNORE_ARGS,2)[1]['function'];
print_r(debug_backtrace())
and it basically crashed my browser with the weight of info it returned. –
Laborer 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! –
Arathorn debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2)[1]['function']
–
Saritasarkaria !DEBUG_BACKTRACE_PROVIDE_OBJECT|DEBUG_BACKTRACE_IGNORE_ARGS
–
Caudex ^
instead of !
? –
Lohse DEBUG_BACKTRACE_PROVIDE_OBJECT
is just an integer constant with a value of 1
, indicating you want the object field populated. Negating that just gives you 0
to indicate the contrary. You don't want to XOR the two constants, you want to negate the first. –
Caudex !
is boolean negation, not binary negation. I actually meant ~
, not ^
. Negating 1
does not do anything, you could negate 2
or 1000
it would still give 0
. I think the proper negation would be ~DEBUG_BACKTRACE_PROVIDE_OBJECT
. –
Lohse 1
, and 2
(implying for example activation of 4
), you would do ~1|2
and not !1|2
. Test: $ php -r 'printf("val=%d lneg=%d bneg=%d lcheck=%d ncheck=%d\n", 1|2, !1|2, ~1|2, (!1|2) & 4, (~1|2) & 4);'
prints val=3 lneg=2 bneg=-2 lcheck=0 ncheck=4
. The 1st check (logical) fails which is not the intent, and the 2nd check (binary) passes which is the intent. –
Lohse 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! :D
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)
. –
Ethnarch As of php 5.4 you can use
$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.
echo $caller;
and should work. ;-) –
Matroclinous $caller = $dbt[1]['function'] ?? null;
–
Lepidopteran isset($something) ? $something : null
can be shortened to $something ?? null
in modern PHP versions. Edit: sorry, someone already covered this –
Commendam debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2)[1]['function'] ?? null;
–
Objectivism 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');
And you get this... (voilà!)
Array ( [file] => /home/lufigueroa/Desktop/test.php [line] => 12 [function] => theCall [args] => Array ( [0] => lucia [1] => php ) )
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 {main}"
My favourite way, in one line!
debug_backtrace()[1]['function'];
You can use it like this:
echo 'The calling function: ' . debug_backtrace()[1]['function'];
Note that this is only compatible with versions of PHP released within the last year. But it's a good idea to keep your PHP up to date anyway for security reasons.
I just wrote a version of this called "get_caller", I hope it helps. Mine is pretty lazy. You can just run get_caller() from a function, you don't have to specify it like this:
get_caller(__FUNCTION__);
Here's the script in full with a quirky test case:
<?php
/* This function will return the name string of the function that called $function. To return the
caller of your function, either call get_caller(), or get_caller(__FUNCTION__).
*/
function get_caller($function = NULL, $use_stack = NULL) {
if ( is_array($use_stack) ) {
// If a function stack has been provided, used that.
$stack = $use_stack;
} else {
// Otherwise create a fresh one.
$stack = debug_backtrace();
echo "\nPrintout of Function Stack: \n\n";
print_r($stack);
echo "\n";
}
if ($function == NULL) {
// We need $function to be a function name to retrieve its caller. If it is omitted, then
// we need to first find what function called get_caller(), and substitute that as the
// default $function. Remember that invoking get_caller() recursively will add another
// instance of it to the function stack, so tell get_caller() to use the current stack.
$function = get_caller(__FUNCTION__, $stack);
}
if ( is_string($function) && $function != "" ) {
// If we are given a function name as a string, go through the function stack and find
// it's caller.
for ($i = 0; $i < count($stack); $i++) {
$curr_function = $stack[$i];
// Make sure that a caller exists, a function being called within the main script
// won't have a caller.
if ( $curr_function["function"] == $function && ($i + 1) < count($stack) ) {
return $stack[$i + 1]["function"];
}
}
}
// At this stage, no caller has been found, bummer.
return "";
}
// TEST CASE
function woman() {
$caller = get_caller(); // No need for get_caller(__FUNCTION__) here
if ($caller != "") {
echo $caller , "() called " , __FUNCTION__ , "(). No surprises there.\n";
} else {
echo "no-one called ", __FUNCTION__, "()\n";
}
}
function man() {
// Call the woman.
woman();
}
// Don't keep him waiting
man();
// Try this to see what happens when there is no caller (function called from main script)
//woman();
?>
man() calls woman(), who calls get_caller(). get_caller() doesn't know who called it yet, because the woman() was cautious and didn't tell it, so it recurses to find out. Then it returns who called woman(). And the printout in source-code mode in a browser shows the function stack:
Printout of Function Stack:
Array
(
[0] => Array
(
[file] => /Users/Aram/Development/Web/php/examples/get_caller.php
[line] => 46
[function] => get_caller
[args] => Array
(
)
)
[1] => Array
(
[file] => /Users/Aram/Development/Web/php/examples/get_caller.php
[line] => 56
[function] => woman
[args] => Array
(
)
)
[2] => Array
(
[file] => /Users/Aram/Development/Web/php/examples/get_caller.php
[line] => 60
[function] => man
[args] => Array
(
)
)
)
man() called woman(). No surprises there.
I needed something to just list the calling classes/methods (working on a Magento project).
While debug_backtrace
provides tons of useful information, the amount of information it spewed out for the Magento installation was overwhelming (over 82,000 lines!) Since I was only concerned with the calling function and class, I worked this little solution up:
$callers = debug_backtrace();
foreach( $callers as $call ) {
echo "<br>" . $call['class'] . '->' . $call['function'];
}
The simplest way of getting parent function name is:
$caller = next(debug_backtrace())['function'];
PHP Notice: Only variables should be passed by reference
- hard coding an array index feels tacky, but I guess if you want a one liner that's what you've got to do. –
Kuo Best answer of that question I've seen is:
list(, $caller) = debug_backtrace(false);
Short and clean
debug_backtrace()[1]['function']
doesn't appeal? –
Framework list(, $caller)
is perfectly valid php; the manual states: "list() constructs can no longer be empty
." That construct is not empty. What is not valid about this answer from 2012--as of php 5.3.6 the method signature is debug_backtrace(int $options)
and does not accept false
. –
Culliton © 2022 - 2024 — McMap. All rights reserved.