On the http://php.net/manual/en/language.operators.precedence.php webpage, the second highest precedence level contains a left-associative operator called [
.
I don't understand that. Is it the [
used to access/modify array entries, as in $myArray[23]
? I cannot imagine any code snippet where we would need to know the "precedence" of it wrt other operators, or where the "associativity" of [
would be useful.
This is a very valid question.
1. Precedence in between [...]
First there is never an ambiguity to what PHP should evaluate first when looking at the right side of the
[
, since the bracket requires a closing one to go with it, and so every operator in between has precedence over the opening bracket.Example:
The
+
has precedence, i.e. first 1+2 has to be evaluated before PHP can determine which element to retrieve from $a.But the operator precedence list is not about this.
2. Associativity
Secondly there is an order of evaluating consecutive pairs of
[]
, like here:PHP will first evaluate
$b[1]
and then apply[2]
to that. This is left-to-right evaluation and is what is intended with left associativity.But the question at hand is not so much about associativity, but about precedence with regards to other operators.
3. Precedence over operators on the left side
The list states that
clone
andnew
operators have precedence over[
, and this is not easy to test.First of all, most of the constructs where you would combine
new
with square brackets are considered invalid syntax. For example, both of these statements:will give a parsing error:
PHP requires you to add parentheses to make the syntax valid. So there is no way we can test the precedence rules like this.
But there is another way, by using a variable containing a class name:
This is valid syntax, but now the challenge is to make a class that creates something that acts like an array.
This is not trivial to do, as an object property is referenced like this:
obj->prop
, not likeobj["prop"]
. One can however use the ArrayObject class which can deal with square brackets. The idea is to extend this class and redefine the offsetGet method to make sure a freshly made object of that class has array elements to return.To make objects printable, I ended up using the magical method __toString, which is executed when an object needs to be cast to a string.
So I came up with this set-up, defining two similar classes:
With this set-up we can test a few things.
Test 1
This statement creates a new TestClass instance, which then needs to be converted to string, so the __toString method is called on that new instance, which returns:
This is as expected.
Test 2
Here we start with the same actions, as the parentheses force the
new
operation to be executed first. This time PHP does not convert the created object to string, but requests array element 0 from it. This request is answered by the offsetGet method, and so the above statement outputs:Test 3
The idea is to force the opposite order of execution. Sadly enough, PHP does not allow this syntax, so will have to break the statement into two in order to get the intended evaluation order:
So now the
[
is executed first, taking the first character of the value of $test, i.e. "T", and thennew
is applied to that. That's why I defined also a T class. Theecho
calls __toString on that instance, which yields:Now comes the final test to see which is the order when no parentheses are present:
Test 4
This is valid syntax, and...
4. Conclusion
The output is:
So in fact, PHP applied the
[
before thenew
operator, despite what is stated in the operator precedence table!5. Comparing
clone
withnew
The
clone
operator has similar behaviour in combination with[
. Strangely enough,clone
andnew
are not completely equal in terms of syntax rules. Repeating test 2 withclone
:yields a parsing error:
But test 4 repeated with
clone
shows that[
has precedence over it.@bishop informed that this reproduces the long standing documentation bug #61513: "
clone
operator precedence is wrong".In PHP you can initialize empty arrays with
[]
so in order to know how to define an array the precedence of the next character defines on how to initialize the array.Since arrays are part of the syntax structure, it is done before any math, it simply has a higher precedence than other calculative operators for that reason.
However in all honesty I don't really understand the question. In most programming languages the
[
and the]
are associated with arrays which is part of the base syntax that always have a high priority (if not the highest)It just means the array variable (left associativity - $first) will be evaluated before the array key (right associativity - $second)
This have lot of sense when array has multiple dimensions