3

Suppose that we have this code (simplified example):

$propertyName = 'items';
$foo = new \stdClass;
$foo->$propertyName = array(42);

At this point I 'd like to write an expression that evaluates to a reference to the value inside the array.

Is it possible to do this? If so, how?

An answer that will "do the job" but is not what I 'm looking for is this:

// Not acceptable: two statements
$temp = &$foo->$propertyName;
$temp = &$temp[0];

But why write it as two statements? Well, because this will not work:

// Will not work: PHP's fantastic grammar strikes again
// This is actually equivalent to $temp = &$foo->i
$temp = &$foo->$propertyName[0];

Of course &$foo->items[0] is another unacceptable solution because it fixes the property name.

In case anyone is wondering about the strange requirements: I 'm doing this inside a loop where $foo itself is a reference to some node inside a graph. Any solution involving $temp would require an unset($temp) afterwards so that setting $temp on the next iteration does not completely mess up the graph; this unset requirement can be overlooked if you are not ultra careful around references, so I was wondering if there is a way to write this code such that there are less possibilities to introduce a bug.

Jon
  • 428,835
  • 81
  • 738
  • 806

2 Answers2

4

Ambiguous expressions like that need some help for the parser:

$temp = &$foo->{$propertyName}[0];

Btw, this is the same regardless if you're looking for the variable alias (a.k.a. reference) or just the value. Both need it if you use the array-access notation.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • 1
    Ouch -- I thought about this, but only tried `&{$foo->$propertyName}[0]` which is a compile-time error... PHP I love you so much more now. Thanks :) – Jon Jun 05 '12 at 12:44
  • Suggested read: [PHP Variable Names: Curly Brace Madness](http://cowburn.info/2008/01/12/php-vars-curly-braces/) and there are some related SO Questions: http://stackoverflow.com/q/1147937/367456 ; http://stackoverflow.com/q/9844185/367456 – hakre Jun 05 '12 at 12:45
  • Normally I 'd say "I know", but here "I should have known" is more appropriate. For more fun, have a look at this: http://stackoverflow.com/questions/10333016/how-to-access-object-properties-with-names-like-integers/10333200#10333200 – Jon Jun 05 '12 at 12:49
2

It took some googling, but I found the solution:

$propertyName = 'items';
$foo = new \stdClass;
$foo->$propertyName = array(42);

$temp = &$foo->{$propertyName}[0]; // note the brackets

$temp++;

echo $temp;
print_r($foo->$propertyName);

This will print 43 array(43).

I found the solution in this article: Referencing an array in a variable object property by Jeff Beeman

Jeroen
  • 13,056
  • 4
  • 42
  • 63
  • +1 and thank you for answering. Wish I could accept both, but hakre was faster. – Jon Jun 05 '12 at 12:45