How to get a variable name as a string in PHP?

前端 未结 24 1386
南旧
南旧 2020-11-22 01:35

Say i have this PHP code:

$FooBar = \"a string\";

i then need a function like this:

print_var_name($FooBar);
相关标签:
24条回答
  • 2020-11-22 01:48

    I made an inspection function for debugging reasons. It's like print_r() on steroids, much like Krumo but a little more effective on objects. I wanted to add the var name detection and came out with this, inspired by Nick Presta's post on this page. It detects any expression passed as an argument, not only variable names.

    This is only the wrapper function that detects the passed expression. Works on most of the cases. It will not work if you call the function more than once in the same line of code.

    This works fine: die(inspect($this->getUser()->hasCredential("delete")));

    inspect() is the function that will detect the passed expression.

    We get: $this->getUser()->hasCredential("delete")

    function inspect($label, $value = "__undefin_e_d__")
    {
        if($value == "__undefin_e_d__") {
    
            /* The first argument is not the label but the 
               variable to inspect itself, so we need a label.
               Let's try to find out it's name by peeking at 
               the source code. 
            */
    
            /* The reason for using an exotic string like 
               "__undefin_e_d__" instead of NULL here is that 
               inspected variables can also be NULL and I want 
               to inspect them anyway.
            */
    
            $value = $label;
    
            $bt = debug_backtrace();
            $src = file($bt[0]["file"]);
            $line = $src[ $bt[0]['line'] - 1 ];
    
            // let's match the function call and the last closing bracket
            preg_match( "#inspect\((.+)\)#", $line, $match );
    
            /* let's count brackets to see how many of them actually belongs 
               to the var name
               Eg:   die(inspect($this->getUser()->hasCredential("delete")));
                      We want:   $this->getUser()->hasCredential("delete")
            */
            $max = strlen($match[1]);
            $varname = "";
            $c = 0;
            for($i = 0; $i < $max; $i++){
                if(     $match[1]{$i} == "(" ) $c++;
                elseif( $match[1]{$i} == ")" ) $c--;
                if($c < 0) break;
                $varname .=  $match[1]{$i};
            }
            $label = $varname;
        }
    
        // $label now holds the name of the passed variable ($ included)
        // Eg:   inspect($hello) 
        //             => $label = "$hello"
        // or the whole expression evaluated
        // Eg:   inspect($this->getUser()->hasCredential("delete"))
        //             => $label = "$this->getUser()->hasCredential(\"delete\")"
    
        // now the actual function call to the inspector method, 
        // passing the var name as the label:
    
          // return dInspect::dump($label, $val);
             // UPDATE: I commented this line because people got confused about 
             // the dInspect class, wich has nothing to do with the issue here.
    
        echo("The label is: ".$label);
        echo("The value is: ".$value);
    
    }
    

    Here's an example of the inspector function (and my dInspect class) in action:

    http://inspect.ip1.cc

    Texts are in spanish in that page, but code is concise and really easy to understand.

    0 讨论(0)
  • 2020-11-22 01:48

    I actually have a valid use case for this.

    I have a function cacheVariable($var) (ok, I have a function cache($key, $value), but I'd like to have a function as mentioned).

    The purpose is to do:

    $colour = 'blue';
    cacheVariable($colour);
    

    ...

    // another session
    

    ...

    $myColour = getCachedVariable('colour');
    

    I have tried with

    function cacheVariable($variable) {
       $key = ${$variable}; // This doesn't help! It only gives 'variable'.
       // do some caching using suitable backend such as apc, memcache or ramdisk
    }
    

    I have also tried with

    function varName(&$var) {
       $definedVariables = get_defined_vars();
       $copyOfDefinedVariables = array();
       foreach ($definedVariables as $variable=>$value) {
          $copyOfDefinedVariables[$variable] = $value;
       }
       $oldVar = $var;
       $var = !$var;
       $difference = array_diff_assoc($definedVariables, $copyOfDefinedVariables);
       $var = $oldVar;
       return key(array_slice($difference, 0, 1, true));
    }
    

    But this fails as well... :(

    Sure, I could continue to do cache('colour', $colour), but I'm lazy, you know... ;)

    So, what I want is a function that gets the ORIGINAL name of a variable, as it was passed to a function. Inside the function there is no way I'm able to know that, as it seems. Passing get_defined_vars() by reference in the second example above helped me (Thanks to Jean-Jacques Guegan for that idea) somewhat. The latter function started working, but it still only kept returning the local variable ('variable', not 'colour').

    I haven't tried yet to use get_func_args() and get_func_arg(), ${}-constructs and key() combined, but I presume it will fail as well.

    0 讨论(0)
  • 2020-11-22 01:50

    This is the way I did it

    function getVar(&$var) {
        $tmp = $var; // store the variable value
        $var = '_$_%&33xc$%^*7_r4'; // give the variable a new unique value
        $name = array_search($var, $GLOBALS); // search $GLOBALS for that unique value and return the key(variable)
        $var = $tmp; // restore the variable old value
        return $name;
    }
    

    Usage

    $city  = "San Francisco";
    echo getVar($city); // city
    

    Note: some PHP 7 versions will not work properly due to a bug in array_search with $GLOBALS, however all other versions will work.

    See this https://3v4l.org/UMW7V

    0 讨论(0)
  • 2020-11-22 01:52

    Why don't you just build a simple function and TELL it?

    /**
     * Prints out $obj for debug
     *
     * @param any_type $obj
     * @param (string) $title
     */
    function print_all( $obj, $title = false )
    {
        print "\n<div style=\"font-family:Arial;\">\n";
        if( $title ) print "<div style=\"background-color:red; color:white; font-size:16px; font-weight:bold; margin:0; padding:10px; text-align:center;\">$title</div>\n";
        print "<pre style=\"background-color:yellow; border:2px solid red; color:black; margin:0; padding:10px;\">\n\n";
        var_export( $obj );
        print "\n\n</pre>\n</div>\n";
    }
    
    print_all( $aUser, '$aUser' );
    
    0 讨论(0)
  • 2020-11-22 01:54

    It may be considered quick and dirty, but my own personal preference is to use a function/method like this:

    public function getVarName($var) {      
      $tmp = array($var => '');
      $keys = array_keys($tmp);
      return trim($keys[0]);
    }
    

    basically it just creates an associative array containing one null/empty element, using as a key the variable for which you want the name.

    we then get the value of that key using array_keys and return it.

    obviously this gets messy quick and wouldn't be desirable in a production environment, but it works for the problem presented.

    0 讨论(0)
  • 2020-11-22 01:56

    Adapted from answers above for many variables, with good performance, just one $GLOBALS scan for many

    function compact_assoc(&$v1='__undefined__', &$v2='__undefined__',&$v3='__undefined__',&$v4='__undefined__',&$v5='__undefined__',&$v6='__undefined__',&$v7='__undefined__',&$v8='__undefined__',&$v9='__undefined__',&$v10='__undefined__',&$v11='__undefined__',&$v12='__undefined__',&$v13='__undefined__',&$v14='__undefined__',&$v15='__undefined__',&$v16='__undefined__',&$v17='__undefined__',&$v18='__undefined__',&$v19='__undefined__'
    ) {
        $defined_vars=get_defined_vars();
    
        $result=Array();
        $reverse_key=Array();
        $original_value=Array();
        foreach( $defined_vars as $source_key => $source_value){
            if($source_value==='__undefined__') break;
            $original_value[$source_key]=$$source_key;
            $new_test_value="PREFIX".rand()."SUFIX";
            $reverse_key[$new_test_value]=$source_key;
            $$source_key=$new_test_value;
    
        }
        foreach($GLOBALS as $key => &$value){
            if( is_string($value) && isset($reverse_key[$value])  ) {
                $result[$key]=&$value;
            }
        }
        foreach( $original_value as $source_key => $original_value){
            $$source_key=$original_value;
        }
        return $result;
    }
    
    
    $a = 'A';
    $b = 'B';
    $c = '999';
    $myArray=Array ('id'=>'id123','name'=>'Foo');
    print_r(compact_assoc($a,$b,$c,$myArray) );
    
    //print
    Array
    (
        [a] => A
        [b] => B
        [c] => 999
        [myArray] => Array
            (
                [id] => id123
                [name] => Foo
            )
    
    )
    
    0 讨论(0)
提交回复
热议问题