Variable Variables Pointing to Arrays or Nested Ob

2019-01-12 10:20发布

Is it possible to create a variable variable pointing to an array or to nested objects? The php docs specifically say you cannot point to SuperGlobals but its unclear (to me at least) if this applies to arrays in general.

Here is my try at the array var var.

     // Array Example
     $arrayTest = array('value0', 'value1');
     ${arrayVarTest} = 'arrayTest[1]';
     // This returns the correct 'value1'
     echo $arrayTest[1];
     // This returns null
     echo ${$arrayVarTest};   

Here is some simple code to show what I mean by object var var.

     ${OBJVarVar} = 'classObj->obj'; 
     // This should return the values of $classObj->obj but it will return null  
     var_dump(${$OBJVarVar});    

Am I missing something obvious here?

4条回答
ゆ 、 Hurt°
2楼-- · 2019-01-12 10:55

In echo $arrayTest[1]; the vars name is $arrayTest with an array index of 1, and not $arrayTest[1]. The brackets are PHP "keywords". Same with the method notation and the -> operator. So you'll need to split up.

// bla[1]
$arr = 'bla';
$idx = 1;
echo $arr[$idx];

// foo->bar
$obj = 'foo';
$method = 'bar';
echo $obj->$method;

What you want to do sounds more like evaluating PHP code (eval()). But remember: eval is evil. ;-)

查看更多
爷的心禁止访问
3楼-- · 2019-01-12 11:02

Array element approach:

  • Extract array name from the string and store it in $arrayName.
  • Extract array index from the string and store it in $arrayIndex.
  • Parse them correctly instead of as a whole.

The code:

$arrayTest  = array('value0', 'value1');
$variableArrayElement = 'arrayTest[1]';
$arrayName  = substr($variableArrayElement,0,strpos($variableArrayElement,'['));
$arrayIndex = preg_replace('/[^\d\s]/', '',$variableArrayElement);

// This returns the correct 'value1'
echo ${$arrayName}[$arrayIndex];

Object properties approach:

  • Explode the string containing the class and property you want to access by its delimiter (->).
  • Assign those two variables to $class and $property.
  • Parse them separately instead of as a whole on var_dump()

The code:

$variableObjectProperty = "classObj->obj";
list($class,$property)  = explode("->",$variableObjectProperty);

// This now return the values of $classObj->obj
var_dump(${$class}->{$property});    

It works!

查看更多
男人必须洒脱
4楼-- · 2019-01-12 11:06

Nope you can't do that. You can only do that with variable, object and function names.

Example:

 $objvar = 'classObj';
 var_dump(${$OBJVarVar}->var);

Alternatives can be via eval() or by doing pre-processing.

$arrayTest = array('value0', 'value1');
$arrayVarTest = 'arrayTest[1]';

echo eval('return $'.$arrayVarTest.';');
eval('echo $'.$arrayVarTest.';');

That is if you're very sure of what's going to be the input.

By pre-processing:

function varvar($str){
  if(strpos($str,'->') !== false){
    $parts = explode('->',$str);
    global ${$parts[0]};
    return $parts[0]->$parts[1];
  }elseif(strpos($str,'[') !== false && strpos($str,']') !== false){
    $parts = explode('[',$str);
    global ${$parts[0]};
    $parts[1] = substr($parts[1],0,strlen($parts[1])-1);
    return ${$parts[0]}[$parts[1]];
  }else{
    return false;
  }
}

$arrayTest = array('value0', 'value1');
$test = 'arrayTest[1]';
echo varvar($test);
查看更多
老娘就宠你
5楼-- · 2019-01-12 11:07

Use = & to assign by reference:

 $arrayTest = array('value0', 'value1');
 $arrayVarTest = &$arrayTest[1];

 $arrayTest[1] = 'newvalue1'; // to test if it's really passed by reference

 print $arrayVarTest;
查看更多
登录 后发表回答