This is a very important issue.
1. Priority between [...]
Firstly, there is never any ambiguity as to what PHP should evaluate first by looking at the right side [ , since the bracket requires closing to go with it, and therefore each statement between them takes precedence over the opening bracket.
Example:
$a[1+2]
+ has priority, i.e. the first 1 + 2 must be evaluated before PHP can determine the element for from $ a.
But the list of operators' priorities is not about that.
2. Associativity
Secondly, there is a procedure for evaluating consecutive pairs [] , as here:
$b[1][2]
PHP will first evaluate $b[1] and then apply to it [2] . This is from left to right assessment and is what is assumed with left associativity.
But the question is not so much in associativity, but in relation to priorities in relation to other operators.
3. Priority over operators on the left
The list indicates that the clone and new operators take precedence over [ , and this is not easy to verify.
First of all, most constructs in which you would combine new with square brackets are considered invalid syntax. For example, both of these statements:
$a = new myClass()[0]; $a = new myClass[0];
will give a parsing error:
syntax error, unexpected '['
PHP requires you to add parentheses to make the syntax valid. Therefore, we cannot verify priority rules like this.
But there is another way, using a variable containing the class name:
$a = new $test[0];
This is a valid syntax, but now the challenge is to create a class that creates something that acts like an array.
This is not so simple as the property of the object is referenced as follows: obj->prop , not as obj["prop"] . However, you can use the ArrayObject class , which can deal with square brackets. The idea is to extend this class and override the offsetGet method to make sure that the newly created object of this class returned the elements of the array.
To make objects printable, I ended up using the __ toString magic method, which runs when the object needs to be wrapped to a string.
So, I came up with this setting by defining two similar classes:
class T extends ArrayObject { public function __toString() { return "I am a T object"; } public function offsetGet ($offset) { return "I am a T object array element"; } } class TestClass extends ArrayObject { public function __toString() { return "I am a TestClass object"; } public function offsetGet ($offset) { return "I am a TestClass object array element"; } } $test = "TestClass";
With this setting, we can verify several things.
Test 1
echo new $test;
This statement creates a new instance of TestClass, which then needs to be converted to string, so the __toString method is called on this new instance, which returns:
I am a TestClass object
This is as expected.
Test 2
echo (new $test)[0];
Here we start with the same actions, since the brackets force the new operation. This time, PHP does not convert the created object to a string, but requests an array element 0 from it. The offsetGet method answers this request, and therefore the output above displays:
I am an array element of a TestClass object
Test 3
echo new ($test[0]);
The idea is to force the opposite order of execution. Unfortunately, PHP does not allow you to use this syntax, so in order to get the estimated evaluation order, you have to break the operator into two parts:
$name = $test[0]; echo new $name;
So now [ is done, taking the first character of the value of $ test, i.e. "T" and then new . This is why I also defined the T. class. echo calls this __toString instance, which gives:
I'm an object of T
Now comes the final test to see what order when there are no parentheses:
Test 4
echo new $test[0];
This is a valid syntax and ...
4. Conclusion
Output:
I'm an object of T
Thus, PHP applied [ before the new operator, despite the fact that it is indicated in the operator priority table !
5. Comparing clone with new
The clone operator has a similar behavior when combined with [ . Oddly enough, clone and new not completely equal in terms of syntax rules. Repeat test 2 with clone :
echo (clone $test)[0];
throws a parsing error:
syntax error, unexpected '['
But test 4, repeated with clone , shows that [ takes precedence over it.
@bishop reported that this reproduces a long-term documentation error # 61513: " clone operator priority is incorrect . "