How can I find out the name of a variable inside a function?

前端 未结 5 917
花落未央
花落未央 2021-01-21 04:46

I have a function

function my_dump($a,$name){
    echo \'
\'.$name.\":\\n\";
    var_export($a);
    echo \'
\'; }

How can

相关标签:
5条回答
  • 2021-01-21 04:57

    If you need to debug code, then using tools like xdebug is a lot more flexible and efficient than homebrew variable dumps; but debug_backtrace() (although a big overhead) might give you what you need. Extract the filename and line number of the call to your debug dump function, and parse that line to extract the variable name that's used when calling the function

    function my_dump($a) {
        $backtrace = debug_backtrace()[0];
        $fh = fopen($backtrace['file'], 'r');
        $line = 0;
        while (++$line <= $backtrace['line']) {
            $code = fgets($fh);
        }
        fclose($fh);
        preg_match('/' . __FUNCTION__ . '\s*\((.*)\)\s*;/u', $code, $name);
        echo '<pre>'.trim($name[1]).":\n";
        var_export($a);
        echo '</pre>';
    }
    
    
    $foo = 'bar';
    
    $baz = array(
        'Hello',
        'World'
    );
    
    my_dump($foo);
    my_dump(
        $baz
    );
    

    If your PHP version doesn't support array dereferencing, change

    $backtrace = debug_backtrace()[0];
    

    to

    $backtrace = debug_backtrace();
    $backtrace = $backtrace[0];
    

    If your call to my_dump() spans multiple lines (like my $baz example), you'll need a slightly more sophisticated parser to extract the variable name from your code.

    0 讨论(0)
  • 2021-01-21 04:59

    There is no way to do this.

    When the function is called the value of the parameter gets pasted into your $a , so every attempt to get the name of it would return "a".

    http://us3.php.net/get_defined_vars will fail, because it only returns variables inside your function (that means "a").

    You may use an array with one item, but I guess that's not what you intend to do.

    0 讨论(0)
  • 2021-01-21 05:04

    ... I beg your pardon for new answer instead change of previous, but it would be too long (and thus uncomfortable) for reading.

    Below is function from previous answer, that is improved for multiple usage of this function. This version is capable to get name of correct variable in case of multiple usage in one line.

    It is not capable to get name of more than one variable - at least because I don't think it would be good (useful for anything).

    Differences:

    • adding of integer parameter $Index
    • new function for regular expression
    • new regular expression
    • new handling of result of regular expression

    • parameter $Index is not demanded - but its ignoring whenever else than the first usage of that function will give wrong result

    • \x20 in expression means space

    • exception class and exception message in try-catch block may be rewritten as you need

    • protected status of function may be changed or deleted

      protected function Get_VariableNameAsText($Variable="", $Index="")
      {
          $File = file(debug_backtrace()[0]['file']);
      
          try
          {
              if(!empty($Index) && !is_integer($Index))
              {
                  throw new UniT_Exception(UniT_Exception::UNIT_EXCEPTIONS_MAIN_PARAM, UniT_Exception::UNIT_EXCEPTIONS_PARAM_VALTYPE);
              }
          }
          catch(UniT_Exception $Exception)
          {
              $Exception -> ExceptionWarning(__CLASS__, __FUNCTION__, $this -> Get_Parameters(__CLASS__, __FUNCTION__)[1], gettype($Index), 'integer');
          }
      
          for($Line = 1; $Line < count($File); $Line++)
          {
              if($Line == debug_backtrace()[0]['line']-1)
              {
                  preg_match_all('/'.__FUNCTION__.'\((?<type>[a-z]{1,}\:{2}\${1}|\$this\x20{0,1}\-\>{1}\x20{0,1}|\${1})(?<variable>[A-Za-z0-9_]{1,})\x20{0,1}\,{0,1}\x20{0,1}(?<index>[0-9]{0,})\x20{0,}\)/', $File[$Line], $VariableName, PREG_SET_ORDER);
      
                  if(empty($Index))
                  {
                      return $VariableName[0]['type'].$VariableName[0]['variable'];
                  }
                  else
                  {
                      return $VariableName[$Index]['type'].$VariableName[$Index]['variable'];
                  }
              }
          }
      }
      

    I hope it will help you, like or better than previous version.

    Edit: New expression allows using of more types of variables (not only common).

    0 讨论(0)
  • 2021-01-21 05:06
    function my_dump($a) {
    $backtrace = debug_backtrace()[0];
    $fh = fopen($backtrace['file'], 'r');
    $line = 0;
    while (++$line <= $backtrace['line']) {
        $code = fgets($fh);
    }
    fclose($fh);
    preg_match('/' . __FUNCTION__ . '\s*\((.*)\)\s*;/u', $code, $name);
    echo '<pre>'.trim($name[1]).":\n";
    var_export($a);
    echo '</pre>';
    }
    

    It does not run right - because used expression does not give correct result.

    Using of \s* has not sense because nothing can be between name of function and brackets with parameters.

    Using of ; in expression has not sense too. At least because is allows only standalone using of this function where result of this function is given to else variable. But sometimes it may be needed to use this function as parameter.

    And using of (.*) will allow also all that is behind variable name given as parameter - even if there is semicolon.

    So, it is needed to exclude of sign of end bracket, ), from result. There are many ways how to do that.

    You can use form from code of function below or this (or something else)

    '/'.__FUNCTION__.'\((\w+)\)/'
    

    Whole function may be very simplified into (for example, this is case of class function):

    protected function Get_VariableNameAsText($Variable="")
    {
        $File = file(debug_backtrace()[0]['file']);
    
        for($Line = 1; $Line < count($File); $Line++)
        {
            if($Line == debug_backtrace()[0]['line']-1)
            {
                preg_match('/'.__FUNCTION__.'\(([^\)]*)\)/', $File[$Line], $VariableName);
                return trim($VariableName[1]);
            }
        }
    }
    

    I deleted using of var_export because I don't see why to use it, when I only want to get variable name as string (text). And printing of given string is better outside of this function.

    If you have not 5.4 or greater, you need to change code

    $File = file(debug_backtrace()[0]['file']);
    if($Line == debug_backtrace()[0]['line']-1)
    

    on

    $Trace = debug_backtrace();
    $File = file($Trace[0]['file']);
    if($Line == $Trace[0]['line']-1)
    
    0 讨论(0)
  • 2021-01-21 05:11

    If it is a simple script, where all variables are defined in the global scope, you could get for the $GLOBALS solution:

    function my_dump($a){
        if(is_string($a) and isset($GLOBALS[$a])) {
            echo "varname: $a\n";
            $a=&$GLOBALS[$a];
        }
        echo '<pre>'.$name.":\n";
        var_export($a);
        echo '</pre>';
    }
    

    this way you can call the dump function with the variable name instead

    my_dump("cool_variable_name");
    

    instead of

    my_dump($cool_variable_name);
    
    0 讨论(0)
提交回复
热议问题