Referencing an array in a variable object property
Update:
Thanks to an anonymous commenter for letting me know that this is an issue of operator precedence.
This is more a personal note than anything, but I've been banging my head against a wall trying to figure out how to reference an array within a variably-named object property in PHP. Having not found anything very useful when search Google, I figure my post may end up being someone's helpful search result. Maybe I just don't know the right terminology for what I'm trying to do...?
Anyways, I've got a module that needs to modify the string in a CCK text field before it's shown to users on the node edit form. It's a "glue" module that helps us handle course enrollment, and the field in question handles course instructor(s) via a comma-delimited list of usernames. The module takes the user's submitted data, parses it into an array and stores each username in a table joined with course ID for other uses (such as passing to our Sakai installation). The CCK field is referenced in several places, so I use an admin settings form to allow us to say, "This CCK field is the field that users fill out to define instructors." This allows us to avoid hard-coding the CCK field name all over our glue module, but it also led to the headache I encountered today.
When a user goes back to the form to edit the course, I want to present the username list cleanly (alphabetical, no accidental whitespace, etc). Here's the code I tried to use:
function ideal_courses_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { // ... (irrelevant stuff here) case 'prepare': $field_instructors = variable_get('ideal_courses_field_instructors', NULL); // The line that fails is below: $node->$field_instructors[0]['value'] = ideal_courses_instructors_as_string($node); break; // ... (more irrelevant stuff here) }
The error I kept getting was, "PHP Fatal error: Cannot use string offset as an array." The strange thing is that doing a print_r($node->$field_instructors); works fine. The fix was simple, but difficult to find: wrap the variable property name in curly braces: $node->{$field_instructors}[0]['value']. The full result is below:
function ideal_courses_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { // ... (irrelevant stuff here) case 'prepare': $field_instructors = variable_get('ideal_courses_field_instructors', NULL); // Fixed line is below: $node->{$field_instructors}[0]['value'] = ideal_courses_instructors_as_string($node); break; // ... (more irrelevant stuff here) }
- Login to post comments

Comments
Actually, the reason it didn't work is because of operator precedence. PHP evaluated the $field_instructors[0]['value'] as a unit first, since [] is very high in the precedence order, and then that expression was then evaluated as $node->{result of expression} where {result of expression} is whatever $field_instructors[0]['value'] evaluates to. It looks like you meant to evaluate first the $node->$field_instructors part first to get a reference to that variable in the object, and then perform the array operations. It's exactly the same problem that makes $a + $b * $c evaluate to something different than ($a + $b) * $c.The curly braces force the precedence to be evaluated in a different order. I imagine that parentheses would've worked too, though I haven't actually tried it with this specific example.
See here for a table of operators and their precedence: http://php.net/operators
Thanks for the details. I actually hadn't ever used the curly brace {expression} syntax before and didn't even know it existed. It makes sense it's something as simple as operator precedence. Thanks for clearing that up!
This worked like a dream! Thank you both so much!
Thanks to both of you for explaining this. I have had the same confusion and previously dealt with it by adding an extra line to break the assignment into an extra step.
This is really useful to know. I never knew object names could be referenced like that. Thanks for posting. It's knowing these little details that can add up to doing really interesting stuff.
i think the poster is correct as to why it fails; but i think is suggesting a solution like:
{$node->$field_instructors}[0]['value']
and that doesn't actually work.
I have always split this into 2 statements; but that doesn't work too well for statements.
I am plenty capable at html and javascript, as well as CSS, but I was wondering if now that our company will be going to a Drupal platform, will I need to know PHP?
Also, if I were to set up my own music website on Drupal, would I need to know PHP?
Yes of course ;)
Thanks for giving me the solution! I am doing nearly the same thing and this helped out a great deal!
Thanks for this, the object->{expression} syntax is very helpful.
Thanks a bunch for this post, exactly what I needed. Normally I accessed the properties of my nested object like:
$this->someObject->someProp
And I needed to access it dynamically through a variable, and was trying this to no avail:
$this->someObject[$prop]
Found this post with a Google search for "php object get property from variable", and now I've got everything working peachy with:
$this->someObject->{$prop}
Thanks again!
Thanks for posting this.
Thanks so much for this posting. I had this same issue.
thank you *so much* for this. second time in a few weeks that I've run into this (also in the drupal context both times)... you're right, it's not easy to find... curly braces. so simple!
Thanks so much! Same scenario as Josh L. and this works perfectly!
Thanks for the page, exactly what I was searching for. I found in the PHP manual the -> object operator is not listed in operator precedence table. Maybe it's more of a language construct than a operator. Anyway I couldn't find the solution until I found this page.