Home » Php » PHP Variable Variables with array key

PHP Variable Variables with array key

Posted by: admin July 12, 2020 Leave a comment

Questions:

Just wondering if there is a way around this (or if it is even possible).

So I have a section of code similar to this. I have a string, with a value that contains square brackets, similar to those used when accessing an array key. I want to create that array key itself by using the strings value. I hope this code makes a little more sense of what I mean.

// String that has a value similar to an array key
$string = 'welcome["hello"]';
$$string = 'thisworks';

// I could then print the array keys value like this
print( $welcome["hello"] );

// This would hopefully output 'thisworks'.

Can’t seem to get it to work correctly, however. Is it possible (or how else can I go about it)?

How to&Answers:

The following is an example following your variable name syntax that resolves array members as well:

// String that has a value similar to an array key
$string = 'welcome["hello"]';

// initialize variable function (here on global variables store)
$vars = $varFunc($GLOBALS);

// alias variable specified by $string
$var = &$vars($string);

// set the variable
$var = 'World';

// show the variable
var_dump($welcome["hello"]); # string(5) "World"

With the following implementation:

/**
 * @return closure
 */
$varFunc = function (array &$store) {
    return function &($name) use (&$store)
    {
        $keys = preg_split('~("])?(\["|$)~', $name, -1, PREG_SPLIT_NO_EMPTY);
        $var = &$store;
        foreach($keys as $key)
        {
            if (!is_array($var) || !array_key_exists($key, $var)) {
                $var[$key] = NULL;
            }
            $var = &$var[$key];
        }
        return $var;
    };
};

As you can not overload variables in PHP, you are limited to the expressiveness of PHP here, meaning there is no write context for variable references as function return values, which requires the additional aliasing:

$var = &$vars($string);

If something like this does not suit your needs, you need to patch PHP and if not an option, PHP is not offering the language features you’re looking for.

See as well the related question: use strings to access (potentially large) multidimensional arrays.

Answer:

In Variable variables characters in a string treated literally. They do not interpret whats inside the string. So [] characters in the $string is not treated as array notation. Rather its treated as a part of the variable name.

after you execute $$string = 'thisworks'; PHP creates a variable with name welcome["hello"] literally with value set to thisworks.

To print it use this notation,

print (${'welcome["hello"]'});

Answer:

No, you can’t do that in such way.
Alternatively, you can set reference variable using

$welcomeHello = &$welcome["hello"]

and then use

$welcomeHello = 'thisworks'

for setting item content.

This would be more correct and even faster way for setting array items.

Answer:

You can use eval, although I really wouldn’t recommend it in a production environment, it does have its benefits.

<?
$string = 'welcome["hello"]';
eval('$' . $string . " = 'thisworks';");

// This also works : eval("$$string = 'thisworks';");

// I could then print the array keys value like this
print( $welcome["hello"] ); // Prints 'thisworks'

Answer:

You could use two variables, one for holding the referenced variable name and the other for holding the key:

<?php
$myArray = array('foo', 'bar', 'baz');
$varName = 'myArray';
$varKey  = 1;
echo ${$varName}[$varKey];
// will echo "bar"

As per why the curly braces for dereferencing $varName:

In order to use variable variables with arrays, you have to resolve an ambiguity problem.
That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable.
The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.

(from https://www.php.net/manual/en/language.variables.variable.php)