Tutorial :PHP function: find argument's variable name, and function calls line number



Question:

I want to do something like this for simplifying logging operations. Any idea what I should put in for ?[1]? and ?[2]??

function log_var($var) {    $line = ?[1]?;    $var_name = ?[2]?;      $line--;      $filepath = 'log-' . date('Y-m-d'). '.txt';    $message  = "$line, $var_name = $var\n";    $fp = fopen($filepath, "a");    fwrite($fp, $message);    fclose($fp);    @chmod($filepath, 0666);    return TRUE;  }  

This how I'd use the function in code (numbers are assumed to be line numbers in actual code):

23  $a = 'hello';  24  log_var($a);  25  $b = 'bye';  26  log_var($b);  

And this is what I want to be written to the log file:

23, a = hello  25, b = bye  

EDIT I converted Paul Dixon function a bit and added the result as an answer. The new form does even MORE than I originally hoped for. Thank you again guys!


Solution:1

This isn't something you can easily do, as the function parameter is an expression which is evaluated before the function is called. Thus, the function can only see the value of that expression, and not the expression itself.

If you really want to do this, you could use debug_backtrace to find the file and line number of the caller, extract that line from the source file, then parse out the expression from the function call. Here's a proof-of-concept:

function dump($value)  {      $trace=debug_backtrace();      $expr="<unknown>";      if (isset($trace[0]['file']))      {          $lines=file($trace[0]['file']);          $line=$lines[$trace[0]['line']-1];          $expr=$line;          $expr=preg_replace('/\s*dump\(/i','', $expr);          $expr=preg_replace('/\);\s*/', '', $expr);        }        echo "$expr is $value\n";  }    //examples...  $a=10;  dump($a);    dump($a+10);  

Clearly nuts. But it works :) You could of course simply pass the name in along with the variable!


Solution:2

You might be able to do something close with Reflection. Aside from that, though, there's not much else.


Solution:3

I played with the function provided by Paul Dixon (accepted answer) and got it into the shape really doing what I want. This could act as a poor-man's debugger, and I hope it will be useful to someone.

Here is the function and example usage/output:

function dump($value)  {      $trace=debug_backtrace();        $expr="<unknown>";      if (isset($trace[0]['file']))      {          $myline = $trace[0]['line'];          $myline--;          $lines=file($trace[0]['file']);          $line=$lines[$trace[0]['line']-1];          $expr=$line;          $expr=preg_replace('/\s*dump\(/i','', $expr);          $expr=preg_replace('/\);\s*/', '', $expr);      }        $handle = @fopen(__FILE__, "r");      if ($handle) {          for ($l=1; $l < $myline+1; $l++) {              $buffer = fgets($handle);          }      }      fclose($handle);        $message = "$myline \t $buffer \t $expr = $value \n\n";      $filepath = 'log.txt';      $fp = fopen($filepath, "a");      fwrite($fp, $message);      fclose($fp);      @chmod($filepath, 0666);      return TRUE;      }  

And here is sample usage (numbers represent line numbers in actual code):

41 //examples...  42 $a='hello';  43 dump($a);  44  45 $b = 'bye';  46 dump($b);  47  48 $c = date('y-m-d');  49 dump($c);  50  51 $c = $a . ' and then ' . $b;  52 dump($c);  

The example will produce this output in the log file:

42  $a='hello';      $a = hello    45  $b = 'bye';      $b = bye    48  $c = date('y-m-d');      $c = 10-05-20    51  $c = $a . ' and then ' . $b;      $c = hello and then bye  


Solution:4

You cannot get variable name.

Though you can make it just

log_var("a",$a);  log_var("b",$b);  


Solution:5

The problem with this is that the variable should have a unique value :(

function log_var($var, $line) {    $var_name = 'unknown';    foreach($GLOBALS as $var_name => $value)      if ($value === $var)        $var_name = $var_name;      $line--;      $filepath = 'log-' . date('Y-m-d'). '.txt';    $message  = "$line, $var_name = $var\n";    $fp = fopen($filepath, "a");    fwrite($fp, $message);    fclose($fp);    @chmod($filepath, 0666);    return TRUE;  }    $a = 'hello';  log_var($a, __LINE__);  

Clarification: you should NOT try to do things like this... it's not recommend and there are probably better ways to do what you want.


Solution:6

I don't know if it can be done, that you get the line number of where the variable is set, what you can do:

function log_var($var, $var_name) {    $backtrace = debug_backtrace();    $line = $backtrace[0]['line']; // get's the line of the call for log_var      $line--;      $filepath = 'log-' . date('Y-m-d'). '.txt';    $message  = "$line, $var_name = $var\n";    $fp = fopen($filepath, "a");    fwrite($fp, $message);    fclose($fp);    @chmod($filepath, 0666);    return TRUE;  }  

So you can do this:

23  $a = 'hello';  24  log_var($a,'$a');  25  $b = 'bye';  26  log_var($b,'$b');  

and the output will, look like this:

23, a = hello  25, b = bye  

I don't believe you can get it any better. But if someone knows how to get it, i'm willing to learn


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »