0

I have read this previous question. My problem is similar: to debug some problems, I need to log all calls to functions in a source file includes/foo.php to database:

<?php
function f1($arg1, $arg2) {
    return $arg1 . "x" . $arg2;
}
...
function f9($foo, $bar=array(), $baz=0) {
    return array(...);
}

What is the simplest way to do this? I've thought of moving includes/foo.php to includes/foo.php_orig, renaming all functions in that source (e.g. f1 to f1__orig, and so on), then put in my own wrapper includes/foo.php:

<?php
include "includes/logger.php";
include "includes/foo.php_orig";
function f1($arg1, $arg2) {
    $res = f1__orig($arg1, $arg2);
    log_fcall(array($arg1, $arg2), $res);
    return $res;
}
...
function f9($foo, $bar=array(), $baz=0) {
    $res = f9__orig($foo, $bar, $baz);
    log_fcall(array($foo, $bar, $baz), $res);
    return $res;
}

But this feels so tedious and manual. Does PHP offer another mechanism? Or at least, some other constructs to ease the pains.

  • 1
    You should probably have a look at http://php.net/manual/en/function.debug-backtrace.php Instead of writing these wrapper functions, I would probably rather copy a one-liner that writes the output of debug_backtrace to a file at the beginning of each of those nine functions. – 04FS Jan 24 '19 at 13:35
  • 1
    Logging backtraces is still a pain. You could be much more comfortable using *xdebug* in conjuction with an IDE having a builtin debugger client, e.g. *netbeans, eclipse, phpstorm*. You can view call stacks and inspect variables at runtime step by step. https://www.youtube.com/watch?v=4Vx8TnNdQ6M – Pinke Helga Jan 24 '19 at 13:47

1 Answers1

0

One way you could do this is using some wrapper magic and eval. This is not to say you should do it, since if this is for debugging, there are much better tools, e.g. debug_baktrace mentioned by 04FS in the comment. Additionally, eval may be disabled for you, depending on where you host your PHP code.

The wrapper would take the intended function name, and an anonymous function, like so:

$wrapped = array();

function logWrap($name, $func) {
  global $wrapped;
  $wrappedIndex = count($wrapped);
  $wrapped[] = $func;
  eval(
    "function ${name}() {"
    . "global \$wrapped;"
    . "\$args = func_get_args();"
    . "\$res = call_user_func_array(\$wrapped[${wrappedIndex}], \$args);"
    . "log_fcall(\$args, \$res);"
    . "return \$res;"
    . "}");
}

Then you can simply wrap your functions like so:

logWrap("f1", function($arg1, $arg2) {
    return $arg1 . "x" . $arg2;
});
Aurel Bílý
  • 7,068
  • 1
  • 21
  • 34