How does "[" be an operator in a PHP language specification?

On the web page http://php.net/manual/en/language.operators.precedence.php, the second highest priority level contains a left-associative operator with the name [ .

I do not understand this. Is [ to access / modify array entries, as in $myArray[23] ? I can’t imagine a piece of code where we would need to know its “priority” in relation to other operators or where “associativity” [ would be useful.

+46
php specifications
Jan 09 '16 at
source share
3 answers

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 . "

+66
Jan 09 '16 at 16:28
source share

It just means that the array variable (left associativity is $ first) will be evaluated before the array key (right associativity is $ second)

 $first[$second] 

This makes a lot of sense when an array has multiple dimensions.

 $first[$second][$third][$fourth] 
+5
Jan 09 '16 at 15:24
source share

In PHP, you can initialize empty arrays with [] , so to know how to define an array, the priority of the next character determines how to initialize the array.

Since arrays are part of the syntax structure, this is done before any mathematics, therefore for this reason it simply has more priority than other computational operators.

 var_dump([5, 6, 7] + [1, 2, 3, 4]); # 5674 - The array must be known before applying the operator 

However, to be honest, I do not quite understand the question. In most programming languages, [ and ] are associated with arrays, which are part of the basic syntax, which always has high priority (if not the highest)

+4
Jan 09 '16 at 2:56
source share



All Articles