16

I know this is not exactly reflection, but kind of. I want to make a debug function that gets a variable and prints a var_dump and the variable name.

Of course, when the programmer writes a call to the function, they already know the variable's name, so they could write something like:

debug( $myvar, 'myvar' );

But I want it to be quick and easy to write, just the function name, the variable, and voilà !

debug( $myvar ); // quicker and easier :)
Petruza
  • 11,744
  • 25
  • 84
  • 136
  • possible duplicate of [How to get a variable name as a string in PHP?](http://stackoverflow.com/questions/255312/how-to-get-a-variable-name-as-a-string-in-php) – outis Oct 01 '10 at 03:53
  • Why we need to get a name of a variable? Which type of situation? – Sasa1234 Mar 09 '16 at 04:39
  • @Sasa1234 Exactly the type of situation I described on the question. – Petruza Mar 09 '16 at 22:55
  • Referring to the variable only is more maintainable in this situation, as well, as using an IDE to rename the variable, for example, would break the earlier version, but not the later one, as the names would no longer match. – fcrick Dec 01 '16 at 18:23
  • Possible duplicate of [How to get a variable name as a string in PHP?](https://stackoverflow.com/q/255312/1255289) – miken32 Jul 24 '18 at 21:31
  • 1
    @miken32 After all these years? – Petruza Aug 01 '18 at 05:17
  • @Petruza always – miken32 Aug 01 '18 at 05:24

11 Answers11

12

You can do it by converting the variable to a key/value set before passing it to the function.

function varName($theVar) {  
   $variableName = key($theVar);  
   $variableValue = $theVar[$variableName];  
   echo ('The name of the variable used in the function call was '.$variableName.'<br />');  
   echo ('The value of the variable used in the function call was '.$variableValue.'<br />');  
}
$myVar = 'abc';
varName(compact('myVar'));

Though I don't recommend creating a reference to a nameless variable, function varName(&$theVar) works too.

Since compact() takes the variable name as a string rather than the actual variable, iterating over a list of variable names should be easy.

As to why you would want to do this -- don't ask me but it seems like a lot of people ask the question so here's my solution.

EngineerGreg
  • 160
  • 1
  • 4
  • Thanks, it's a good one. As to why I would do this, it's in the original post: `I want to make a debug function that gets a variable and prints a var_dump and the variable name.` Although now that I see, it requires calling compact(), but anyway it's already proven that there's no solution like the one I was looking for. – Petruza Feb 03 '11 at 13:43
5

I know I'm answering a 4 year old question but what the hell...

compact() might help you is your friend here!

I made a similar function to quickly dump out info on a few chosen variables into a log for debugging errors and it goes something like this:

function vlog() {
    $args = func_get_args();
    foreach ($args as $arg) {
        global ${$arg};
    }
    return json_encode(compact($args));
}

I found JSON to be the cleanest and most readable form for these dumps for my logs but you could also use something like print_r() or var_export().

This is how I use it:

$foo = 'Elvis';
$bar = 42;
$obj = new SomeFancyObject();

log('Something went wrong! vars='.vlog('foo', 'bar', 'obj'));

And this would print out like this to the logs:

Something went wrong! vars={"foo":"Elvis","bar":42,"obj":{"nestedProperty1":1, "nestedProperty2":"etc."}}

Word of warning though: This will only work for variables declared in the global scope (so not inside functions or classes. In there you need to evoke compact() directly so it has access to that scope, but that's not really that big of a deal since this vlog() is basically just a shortcut for json_encode(compact('foo', 'bar', 'obj')), saving me 16 keystrokes each time I need it.

4

Nope, not possible. Sorry.

chaos
  • 122,029
  • 33
  • 303
  • 309
4

Not elegantly... BUT YOU COULD FAKE IT!

  • 1) Drink enough to convince yourself this is a good idea (it'll take a lot)
  • 2) Replace all your variables with variable variables:
$a = 10
//becomes
$a = '0a';
$$a = 10;
  • 3) Reference $$a in all your code.
  • 4) When you need to print the variable, print $a and strip out the leading 0.

Addendum: Only do this if you are

  • Never showing this code to anyone
  • Never need to change or maintain this code
  • Are crazy
  • Not doing this for a job
  • Look, just never do this, it is a joke
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
3

I know this is very very late, but i did it in a different way.

It might honestly be a bit bad for performance, but since it's for debugging it shouldn't be a problem.

I read the file where the function is called, on the line it was called and I cut out the variable name.

function dump($str){
    // Get the caller with debug backtrace
    $bt = debug_backtrace();
    $caller = array_shift($bt);

    // Put the file where the function was called in an array, split by lines
    $readFileStr = file($caller['file']);

    // Read the specific line where the function was called
    $lineStr = $readFileStr[$caller['line'] -1];

    // Get the variable name (including $) by taking the string between '(' and ')'
    $regularOutput = preg_match('/\((.*?)\)/', $lineStr, $output);
    $variableName = $output[1];

    // echo the var name and in which file and line it was called
    echo "var: " . $variableName . " dumped in file: " . $caller['file'] . ' on line: ' . $caller['line'] . '<br>';

    // dump the given variable
    echo '<pre>' . var_export($str, true) . '</pre>';
}
Dylan Bos
  • 93
  • 7
2

No, the closer you will get is with get_defined_vars().

EDIT: I was wrong, after reading the user comments on get_defined_vars() it's possible with a little hack:

function ev($variable){
    foreach($GLOBALS as $key => $value){
        if($variable===$value){
            echo '<p>$'.$key.' - '.$value.'</p>';
        }
    }
}

$lol = 123;

ev($lol); // $lol - 123

Only works for unique variable contents though.

Alix Axel
  • 151,645
  • 95
  • 393
  • 500
2

i've had the same thought before, but if you really think about it, you'll see why this is impossible... presumably your debug function will defined like this: function debug($someVar) { } and there's no way for it to know the original variable was called $myvar.

The absolute best you could do would be to look at something like get_defined_vars() or $_GLOBALS (if it were a global for some reason) and loop through that to find something which matches the value of your variable. This is a very hacky and not very reliable method though. Your original method is the most efficient way.

nickf
  • 537,072
  • 198
  • 649
  • 721
  • It's not completely ridiculous to think that such a capability might be possible, but it would require `ReflectionParameter` having tracking for the source variable name *if* one exists (presumably it would be null when an rvalue is passed), and it doesn't. – chaos Aug 13 '09 at 14:00
  • Yes, I was like 99% sure it wasn't possible before making the question, but there's always someone on SO that knows more than you so... And thinking about how loosely typed and un-strict PHP is, this woudn't be such a crazy feature. Anyway, it's not _that_ useful, so me: stop dreaming. – Petruza Aug 13 '09 at 15:59
1

Bit late to the game here, but Mach 13 has an interesting solution: How to get a variable name as a string in PHP

Rudu
  • 15,682
  • 4
  • 47
  • 63
  • Rudu, I do not think Mach 13 solution would count as a solution to what has been asked here. @see also http://marc.info/?l=php-general&m=112174126218786&w=2 – rjha94 Aug 26 '11 at 05:32
  • @rjha94 - You're two years late mate and did you read the article? Rasmus' post is linked and yet there's a solution both there, and in the accepted answer (by @EngineerGreg) above. – Rudu Aug 26 '11 at 14:16
  • The link is dead, please update. – Wiktor Stribiżew Sep 18 '21 at 15:18
0

You could use eval:

function debug($variablename)
{
  echo ($variablename . ":<br/>");
  eval("global $". $variablename . ";");
  eval("var_dump($" . $variablename . ");");
}

Usage: debug("myvar") not debug($myvar)

Waggers
  • 606
  • 3
  • 15
  • not only does this not work (your function won't have the right scope), but there's a much better way to do the same thing with Variable Variables: `$$variablename` – nickf Aug 13 '09 at 14:05
  • I've changed the function to account for the loss of scope. I'm not to familiar with variable variables but will take your word for it! – Waggers Aug 13 '09 at 14:16
  • No need to eval, just use variable variables. – Alix Axel Aug 13 '09 at 14:23
  • 1
    yes, but this solution, as well as eyze's work only for globals. But thanks anyway! – Petruza Aug 13 '09 at 16:01
  • 1
    debug("a; mysql_query('DELETE FROM `users` WHERE 1');") – nickf Aug 13 '09 at 23:12
0

This is late post but I think it is possible now using compact method

so the code would be

$a=1;
$b=2;
$c=3

var_dump(compact('a','b','c'));

the output would be

array (size=3)
'a' => int 1
'b' => int 2
'c' => int 3

where variable name a, b and c are the key

Hope this helps

usrNotFound
  • 2,680
  • 3
  • 25
  • 41
-1

I believe Alix and nickf are suggesting this:

function debug($variablename)
{
  echo ($variablename . ":<br/>");
  global $$variablename; // enable scope
  var_dump($$variablename);
}

I have tested it and it seems to work just as well as Wagger's code (Thanks Wagger: I have tried so many times to write this and the global variable declaration was my stumbling block)

Trefs
  • 1