1

Can I do this, maybe using ReflectionClass ?

myprintr($some_object);


function myprintr(){
  foreach(func_get_args() as $key => $arg){

    // here I want to get the name of the passed variable, "some_object"
    // $key seems to be numeric...
  }


}
Alex
  • 66,732
  • 177
  • 439
  • 641
  • 1
    You can't, unless you use something like debug_backtrace(), and there shouldn't really be any need for you to do so... is this a business requirement? or just exploring PHP? – Mark Baker Feb 14 '12 at 15:42
  • I'm trying to create a print_r/var_dump kind of function for my API, and need this name in case the user passes a object and I'm listing the object methods. I want to prepend the variable name to the method names when displaying them, like $object->method... – Alex Feb 14 '12 at 15:44
  • Possibly answered here: http://stackoverflow.com/questions/255312/how-to-get-a-variable-name-as-a-string-in-php – Duane Gran Feb 14 '12 at 15:45
  • 2
    The var name used in the call has no meaning outside of the calling function... I can call myprintr() using $xyz in one place, $abc in another and "hello world" in a third. Most people use phpdocumentor blocks for API docs – Mark Baker Feb 14 '12 at 15:46
  • yes, but you know people use print_r a lot, so I think a localized-version of it would be welcome.. – Alex Feb 14 '12 at 15:47
  • Even with `debug_backtrace()` you can't: http://codepad.org/40nQwFRu – PiTheNumber Feb 14 '12 at 15:48
  • @PiTheNumber - it's awkward, but you could... use debug_bcktrace() to retrieve the file/line number of the calling function, then read that file to extract the relevant piece of scripted code that made the call and parse it to get the variable name (watching out for call_user_func(), lambdas and variants)... unless it's in an eval block – Mark Baker Feb 14 '12 at 15:50
  • Why not just call print_r and use a output buffer to capture it for your API? No need to reinvent the wheel. – Casey Kinsey Feb 14 '12 at 15:52
  • @Alex: what are you really trying to achieve? – Karoly Horvath Feb 14 '12 at 16:09
  • @Casey: I don't need most of the stuff that print_r displays; I just need to list array contents, object property names and values, and object method names with their default arguments as links which link to the documentation page for that method... Anyway I don't think the purpose is important here – Alex Feb 14 '12 at 16:11
  • 1
    @Alex: [xdebug](http://xdebug.org/) will show you the kind of stuff that you seem to be interested in seeing out of the box. – FtDRbwLXw6 Feb 14 '12 at 16:15
  • why r u guys -1-ing me? it's a legitimate question :P – Alex Feb 14 '12 at 17:46
  • @Alex because its the first answer in the Related section and when I type in your exact question title into the Search box I get multiple questions asking the same, e.g. you didnt research properly. – Gordon Feb 14 '12 at 18:24
  • But there are no answers there that show how to do this.. – Alex Feb 14 '12 at 18:41
  • @Alex because its impossible. well, unless you want to use `debug_backtrace` to find where the function was called, load that file into a php parser and tokenize the source code to return the variable name (given that there is a variable name at all) – Gordon Feb 14 '12 at 19:17
  • 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:30

4 Answers4

6

You cannot get the name of the "variable", as there is no variable.

eg:

myprintr("test");
myprintr(myotherfun());

Note: I'm not sure what you are trying to do, but I just feels terrifyingly wrong.. the whole point of functions and objects is to create barriers, and it shouldn't matter what is in the caller's context..

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • @PiTheNumber: that only works with globals... and if the objects is stored in multiple variables, how would you know which one to pick? – Karoly Horvath Feb 14 '12 at 16:05
2

If the user passes an object to myprintr(), then you can use

if (is_object($arg)) {
    $className = get_class($arg);
}

to get the name of the object type that has been passed, which you can then feed to reflection

but the reflection constructor will accept either a class name or an object as an argument, so you don't even need the class name to instantiate a reflection class

EDIT

Just for the sake of playing a bit with this concept (and not creating any dependency on globals), or on whether the arguments are variables, values returned from functions, strings, etc:

class Test{};

function myTest() {
    $some_object = new Test();
    myprintr($some_object);
}

function myprintr(){
    $callStack = debug_backtrace();
    $calledAt = $callStack[0];

    $callingFile = file($calledAt['file'],FILE_IGNORE_NEW_LINES);
    $callingLine = $callingFile[$calledAt['line']-1];
    $callingLine = substr($callingLine,strpos($callingLine,__METHOD__));
    $calledWithArgNames = trim(substr($matches[0],1,-1));

    var_dump($calledWithArgNames);

    $args = func_get_args();

    foreach($args as $arg) {
        var_dump($arg);
    }
}

myTest();

$some_object = new Test();
$some_other_object = &$some_object;

$t = 2;
$gazebo = "summer house";
$visigoth = pi() / 2; myprintr($some_other_object,pi(), atan2(pi(),$t), $visigoth, "Hello $t World", $gazebo); $t = log($t/$visigoth);

This retrieves all the arguments passed by the calling function in $calledWithArgNames, so for the first call you have:

'$some_object'

and for the second call:

'$some_other_object,pi(), atan2(pi(),$t), $visigoth, "Hello $t World", $gazebo'

This still requires splitting down into the individual arguments (a preg_split on commas, except where they're inside braces), but is certainly a step closer to what you're actually asking for.

Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • I'm using this already as a prefix for static methods. For non-static methods I wanted to display that variable name, but if it's not possible I'' just use the class name .. – Alex Feb 14 '12 at 16:14
1

You can't access argument names that don't exist: myprintr doesn't specify any variable names, and func_get_args() will only ever return a numerically indexed array.

I suppose you could add docblock comments and access them with reflection, but this seems like an extraordinary amount of overhead for functionality that you most likely don't need anyway. Using reflection on the function's arguments itself won't do anything for you because, again, you didn't specify any arguments in the function's argument signature.

PHP function arguments are ordered. They aren't something you can reference like an associative array. If you want access to "associative" type key names for a function or method's arguments, you'll have to specify an array argument and pass a value with the associative keys you want, like this:

myfunc(array $args=[])
{
  $key1 = isset($args['key1']) ? $args['key1'] : NULL;
  $key2 = isset($args['key2']) ? $args['key2'] : NULL;
}
  • I'm in this to learn as well, so please let me know what's wrong with the answer when you downvote. Especially if there's a problem, that way it can be amended or removed. Thanks, retroactively, for being zero help. –  Feb 14 '12 at 15:51
  • Nothing as far as I can tell. – Lightness Races in Orbit Feb 14 '12 at 15:52
0

If it is an object you can use func_get_args() and spl_object_hash() to identify the object and then search it in $GLOBALS. There you find the name.

class Test{};
$some_object = new Test();
myprintr($some_object);

function myprintr(){
  $args = func_get_args();
  $id = spl_object_hash($args[0]);
  foreach($GLOBALS as $name => $value)
  {
     if (is_object($value) && spl_object_hash($value) == $id) echo $name;
  }
}

http://codepad.org/gLAmI511

PiTheNumber
  • 22,828
  • 17
  • 107
  • 180
  • what if the object isn't defined in $GLOBALS? – Mark Baker Feb 14 '12 at 16:01
  • 1
    @Alex - only works if the object is defined in $GLOBALS, forget about using it if the object is instantiated in a function or another object method in your code - http://codepad.org/NlwIdR9N – Mark Baker Feb 14 '12 at 16:04
  • 1
    @PiTheNumber - getDefinedVars within the myprintr() function will only return varibles that are in scope within that function – Mark Baker Feb 14 '12 at 16:07
  • @PiTheNumber: that only works with globals... and even then, if the objects is stored in multiple variables, how would you know which one to pick? – Karoly Horvath Feb 14 '12 at 16:08
  • Knock yourself out with: $some_object = new Test(); $some_other_object = &$some_object; myprintr($some_other_object); – Mark Baker Feb 14 '12 at 16:10
  • Yes I know it does not work always. But it's still fun that it is possible at all. :) – PiTheNumber Feb 14 '12 at 16:19