Search code examples
phpvariablessuperglobals

Get value of variable by name in case it is array item, possibly from superglobal


Is this at all possible to get a value from variable accessed by name in case it refers to an indexed array item? Actually I planned to do this trick with $_SERVER['HTTP_HOST'] but I found out that $$ doesn't get well with any specific array item.

$a = '555';
$b = 'a';
var_dump($$b);

$a = array (1,2,3);
$b = 'a';
var_dump($$b);
$b = 'a[1]';
var_dump($$b);

First two vardumps work as expected, but the last one gives Notice: Undefined variable: a[1] even though it obviously exists. And I want it to return 2.

upd: PHP 7.1.16


Solution

  • Here is simple parser for just arrays of strings or numbers

    function parse($str) {
        // regex explanation:
        // ^ - beging of the string
        // valid name inside capture group with at least one character
        // \[ literal open bracket
        // ([^\]]+) - capture group with non closing bracket
        // \] - closing bracket
        // $ - end of string
        $re = "/^([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\[([^\]]+)\]$/";
        if (preg_match($re, $str, $match)) {
            $var = $match[1];
            global $$var;
            // regex for any integer
            if (preg_match("/^[0-9]+$/", $match[2])) {
                // convert integera like string to integer
                return $$var[intval($match[2])];
            } else {
                // remove quotes from beginning and ending of a string
                return $$var[trim($match[2], "\"'")];
            }
        } else {
            return $$str;
        }
    }
    
    $a = array (1,2,3);
    $b = 'a';
    var_dump($$b);
    $b = 'a[1]';
    var_dump(parse($b));
    
    $a = array("foo" => "hello");
    $b = 'a["foo"]';
    var_dump(parse($b));
    echo parse("_SERVER['HTTP_HOST']");
    

    regex for variable name can be found in php docs

    the only limitation is that variable need to be global, but _SERVER is always global so it shouldn't matter.