158

Is there a PHP function to find out the name of the caller function in a given function?

miken32
  • 42,008
  • 16
  • 111
  • 154
  • You should use Xdebug. See my answer in this post : http://stackoverflow.com/questions/1513069/how-can-i-get-the-callee-in-php/9934639#9934639 – svassr Mar 29 '12 at 22:48
  • 16
    Xdebug is categorically not just a PHP function, which was the original request. If you want to e.g. use the caller function name in later PHP logic and not install XDebug on production servers, you need a PHP function. – J-P Jul 06 '12 at 10:37

13 Answers13

226

See debug_backtrace - this can trace your call stack all the way to the top.

Here's how you'd get your caller:

$trace = debug_backtrace();
$caller = $trace[1];

echo "Called by {$caller['function']}";
if (isset($caller['class']))
    echo " in {$caller['class']}";
Community
  • 1
  • 1
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
  • 61
    It seems to me that this prints the callee function name. Use `list(, $caller) = debug_backtrace(false);` to get caller, `false` for performance ;-) (php5.3) – Markus Hedlund Feb 17 '10 at 22:17
  • Many solutions seen on the web get the second element of the backtrace array to get the instance caller: can we be so sure about it? Is the second element always the one we are searching for? I thought a __construct() which includes inside another call such as parent::__construct() could shift of another position the real caller (did not tried yet). – yodabar Aug 30 '11 at 10:10
  • 1
    I tried checking the order of the callers returned while using a ReflectionClass, and it obviously changes the position of the "real" caller method, which is visible in the user interface, so no assumption on the backtrace position can be made. – yodabar Aug 30 '11 at 10:28
  • 4
    array shift will remove first element and return the removed element. The original array will be modified and this should give the required result `echo 'called by '.$trace[0]['function']` – GoodSp33d Jun 20 '12 at 07:44
  • 24
    `debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];` to get caller name with better performmance. – ahuigo Apr 08 '15 at 07:19
  • great function, thanks `function getCallingFunction(){ $trace = debug_backtrace(); $caller = $trace[2]; echo "
    Called by {$caller['function']}"; if (isset($caller['class'])) echo " in {$caller['class']}
    "; }`
    – John Boe Mar 22 '16 at 22:59
18

Xdebug provides some nice functions.

<?php
  Class MyClass
  {
    function __construct(){
        $this->callee();
    }
    function callee() {
        echo sprintf("callee() called @ %s: %s from %s::%s",
            xdebug_call_file(),
            xdebug_call_line(),
            xdebug_call_class(),
            xdebug_call_function()
        );
    }
  }
  $rollDebug = new MyClass();
?>

will return trace

callee() called @ /var/www/xd.php: 16 from MyClass::__construct

To install Xdebug on ubuntu the best way is

sudo aptitude install php5-xdebug

You might need to install php5-dev first

sudo aptitude install php5-dev

more info

svassr
  • 5,538
  • 5
  • 44
  • 63
16

This is very late but I would like to share the function that will give name of the function from which current function is called.

public function getCallingFunctionName($completeTrace=false)
    {
        $trace=debug_backtrace();
        if($completeTrace)
        {
            $str = '';
            foreach($trace as $caller)
            {
                $str .= " -- Called by {$caller['function']}";
                if (isset($caller['class']))
                    $str .= " From Class {$caller['class']}";
            }
        }
        else
        {
            $caller=$trace[2];
            $str = "Called by {$caller['function']}";
            if (isset($caller['class']))
                $str .= " From Class {$caller['class']}";
        }
        return $str;
    }

I hope this will be useful.

MANISH ZOPE
  • 1,181
  • 1
  • 11
  • 28
16

debug_backtrace() supplies details of parameters, function/method calls in the current call stack.

aksu
  • 5,221
  • 5
  • 24
  • 39
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
15
echo debug_backtrace()[1]['function'];

Works since PHP 5.4.

Or optimised (e.g. for non-debug use cases):

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

The first argument prevents to populate unused function arguments, the second limits the trace to two levels (we need the second).

flori
  • 14,339
  • 4
  • 56
  • 63
7

Made this and using this myself

/**
 * Gets the caller of the function where this function is called from
 * @param string what to return? (Leave empty to get all, or specify: "class", "function", "line", "class", etc.) - options see: http://php.net/manual/en/function.debug-backtrace.php
 */
function getCaller($what = NULL)
{
    $trace = debug_backtrace();
    $previousCall = $trace[2]; // 0 is this call, 1 is call in previous function, 2 is caller of that function

    if(isset($what))
    {
        return $previousCall[$what];
    }
    else
    {
        return $previousCall;
    }   
}
Paul Gobée
  • 521
  • 5
  • 12
3

I just wanted to state that flori's way won't work as a function because it will always return the called function name instead of the caller, but I don't have reputation for commenting. I made a very simple function based on flori's answer that works fine for my case:

class basicFunctions{

    public function getCallerFunction(){
        return debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
    }

}

EXAMPLE:

function a($authorisedFunctionsList = array("b")){
    $ref = new basicFunctions;
    $caller = $ref->getCallerFunction();

    if(in_array($caller,$authorisedFunctionsList)):
        echo "Welcome!";
        return true;
    else:
        echo "Unauthorised caller!";
        return false; 
    endif;
}

function b(){
    $executionContinues = $this->a();
    $executionContinues or exit;

    //Do something else..
}
lrd
  • 302
  • 2
  • 12
2

This one worked best for me: var_dump(debug_backtrace());

Gershon Herczeg
  • 3,016
  • 23
  • 33
2

You can extract this information from the array returned by debug_backtrace

Richard Turner
  • 12,506
  • 6
  • 36
  • 37
1

Actually I think debug_print_backtrace() does what you need. http://php.net/manual/en/function.debug-print-backtrace.php

vrijdenker
  • 1,371
  • 1
  • 12
  • 25
0

This should work:

$caller = next(debug_backtrace())['function'];
kenorb
  • 155,785
  • 88
  • 678
  • 743
0

This will do it nicely:


// Outputs an easy to read call trace
// Credit: https://www.php.net/manual/en/function.debug-backtrace.php#112238
// Gist: https://gist.github.com/UVLabs/692e542d3b53e079d36bc53b4ea20a4b

Class MyClass{

public function generateCallTrace()
{
    $e = new Exception();
    $trace = explode("\n", $e->getTraceAsString());
    // reverse array to make steps line up chronologically
    $trace = array_reverse($trace);
    array_shift($trace); // remove {main}
    array_pop($trace); // remove call to this method
    $length = count($trace);
    $result = array();
   
    for ($i = 0; $i < $length; $i++)
    {
        $result[] = ($i + 1)  . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering
    }
   
    return "\t" . implode("\n\t", $result);
}

}

// call function where needed to output call trace

/**
Example output:
1) /var/www/test/test.php(15): SomeClass->__construct()
2) /var/www/test/SomeClass.class.php(36): SomeClass->callSomething()
**/```
Uriahs Victor
  • 1,049
  • 14
  • 32
0

I created a generic class, which can be helpful to many people who want to see the caller method's trace in a user-readable way. As in one of my projects we needed such information to be logged.

use ReflectionClass;

class DebugUtils
{
    /**
     * Generates debug traces in user readable form
     *
     * @param integer $steps
     * @param boolean $skipFirstEntry
     * @param boolean $withoutNamespaces
     * @return string
     */
    public static function getReadableBackTracke(
        $steps = 4,
        $skipFirstEntry = true,
        $withoutNamespaces = true
    ) {
        $str = '';
        try {
            $backtrace = debug_backtrace(false, $steps);

            // Removing first array entry
            // to make sure getReadableBackTracke() method doesn't gets displayed
            if ($skipFirstEntry)
                array_shift($backtrace);

            // Reserved, so it gets displayed in calling order
            $backtrace = array_reverse($backtrace);

            foreach ($backtrace as $caller) {
                if ($str) {
                    $str .= ' --> ';
                }
                if (isset($caller['class'])) {
                    $class = $caller['class'];
                    if ($withoutNamespaces) {
                        $class = (new ReflectionClass($class))->getShortName();
                    }
                    $str .= $class . $caller['type'];
                }
                $str .= $caller['function'];
            }
        } catch (\Throwable $th) {
            return null;
        }

        return $str;
    }
}

Usage: DebugUtils::getReadableBackTracke()

Sample output:

SomeClass->method1 --> SomeOtherClass->method2 --> TargetClass->targetMethod

Do good and keep helping others, happy coding :)

Imran Zahoor
  • 2,521
  • 1
  • 28
  • 38