“[”如何成为PHP语言规范中的运算符?

时间:2016-01-09 14:42:32

标签: php specifications

http://php.net/manual/en/language.operators.precedence.php网页上,第二高的优先级包含一个名为[的左关联运算符。

我不明白。是[用于访问/修改数组条目,如$myArray[23]中所示?我无法想象任何代码片段,我们需要知道其他运算符的“优先级”,或者[的“关联性”有用。

3 个答案:

答案 0 :(得分:67)

这是一个非常有效的问题。

1。优先于[...]

首先看看PHP应该首先评估的内容从来没有含糊不清 [的右侧,因为括号需要关闭它,所以 中间的每个运算符都优先于开括号。

示例:

$a[1+2]

+具有优先权,即必须首先评估 1 + 2 ,然后才能确定哪个 1 + 2 要从 $ a 中检索的元素。

但运算符优先级列表与此无关。

2。结合性

其次,有一个评估连续[]对的顺序,如下所示:

$b[1][2]

PHP将首先评估$b[1],然后将[2]应用于此。这是从左到右 评估是左关联性的目的。

但手头的问题不在于关联性,而在于关于其他运营商的优先级。

3。优先于左侧的运营商

该列表指出clonenew运算符优先于[,这不容易测试。

首先,将new与方括号组合在一起的大多数结构都被视为无效 句法。例如,这两个陈述:

$a = new myClass()[0];
$a = new myClass[0];

会给出解析错误:

  

语法错误,意外' ['

PHP要求您添加括号以使语法有效。所以我们无法测试 像这样的优先规则。

但是还有另一种方法,通过使用包含类名的变量:

$a = new $test[0];

这个有效的语法,但现在的挑战是创建一个创建一些东西的类 这就像一个数组。

这不是一件容易的事,因为对象属性的引用如下:obj->prop,而不是 比如obj["prop"]。然而,可以使用可以处理方括号的ArrayObject class。我们的想法是扩展这个类并重新定义offsetGet method以确保该类的新制作对象具有要返回的数组元素。

为了使对象可打印,我最终使用了魔法方法__toString,当需要将对象强制转换为字符串时执行该方法。

所以我想出了这个设置,定义了两个类似的类:

class T extends ArrayObject {
    public function __toString() {
        return "I am a T object";
    } 
    public function offsetGet ($offset)  {
        return "I am a T object's 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's array element";
    }
}

$test = "TestClass";

通过这种设置,我们可以测试一些事情。

测试1

echo new $test;

此语句创建一个新的 TestClass 实例,然后需要将其转换为 字符串,因此在该新实例上调用 __ toString 方法,该实例返回:

  

我是TestClass对象

这是预期的。

测试2

echo (new $test)[0];

这里我们从相同的动作开始,因为括号强制首先执行new操作。这次PHP不会将创建的对象转换为字符串,而是从中请求数组元素0。该请求由 offsetGet 方法回答,因此上述语句输出:

  

我是TestClass对象的数组元素

测试3

echo new ($test[0]);

这个想法是强制执行相反的顺序。遗憾的是,PHP不允许这种语法,因此必须将语句分成两部分才能获得预期的评估顺序:

$name = $test[0];
echo new $name;

所以现在首先执行[,取值的第一个字符 $ test ,即" T" ,然后new应用于此。这就是我的原因 还定义了一个 T 类。 echo调用该实例上的 __ toString ,产生:

  

我是T对象

现在进行最后的测试,看看没有括号时的顺序是什么:

测试4

echo new $test[0];

这是有效的语法,并且......

4。结论

输出结果为:

  

我是T对象

事实上,PHP在[运算符之前应用了new,尽管在 operator precedence table

5。将clonenew

进行比较

clone运算符与[具有相似的行为。奇怪的是,clonenew在语法规则方面并不完全相同。使用clone重复测试2:

echo (clone $test)[0];

产生解析错误:

  

语法错误,意外' ['

但是使用clone重复测试4表明[优先于它。

@bishop告知,这会重现长期存在的文档错误#61513: "clone operator precedence is wrong"

答案 1 :(得分:5)

这只是意味着数组变量(左关联 - $ first)将在数组键之前进行评估(右关联 - $ second)

$first[$second]

当数组有多个维度时,这很有意义

$first[$second][$third][$fourth]

答案 2 :(得分:4)

在PHP中,您可以使用[]初始化空数组,因此为了知道如何定义数组,下一个字符的优先级定义了如何初始化数组。

由于数组是语法结构的一部分,因此它在任何数学运算之前完成,因此它的优先级高于其他计算运算符。

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

但是说实话,我并不是真的理解这个问题。在大多数编程语言中,[]与数组相关联,这是基本语法的一部分,始终具有高优先级(如果不是最高的)