我最近在PHP代码中看到了这一行:
$dbObject = json_decode($jsonString);
$dbObject->{'mysql-5.4'}[0]->credentials
这是什么意思?在我们可以阅读的PHP docs中,
方括号和花括号可以互换使用来访问数组元素(例如$ array [42]和$ array {42}在上面的例子中都会做同样的事情)。
但是如何定义Object $ dbObject以允许->{...}[...]
访问?这段代码有点不安全吗?哪个PHP版本允许这个?
我错过了PHP文档中的任何内容吗?
答案 0 :(得分:22)
这是为了允许访问属于无效语法的属性作为裸文字。含义:
$dbObject->mysql-5.4[0]->credentials
这是无效/模糊的语法。为了向PHP明确mysql-5.4
是属性而不是属性减去浮点数,您需要使用{'..'}
语法。
确切地说,->{..}
使您可以使用任何表达式作为属性名称。例如:
$dbObject->{ sprintf('%s-%.1f', 'mysql', 5.4) }
答案 1 :(得分:3)
示例中的花括号语法不是来自数组语法,而是来自可能的语法来访问具有变量名称的变量。
也可以使用大括号来清楚地界定属性名称。 在访问属性中的值时,它们最有用 包含一个数组,当属性名称由多个部分组成时, 或者当属性名称包含其他字符时 有效(例如来自json_decode()或SimpleXML)。
PHP文档中的示例:
rest_mod
请参阅“PHP变量变量”:http://php.net/manual/en/language.variables.variable.php (关于那里使用的更多例子......)
答案 2 :(得分:3)
作为@deceze's answer的补充:
->
运算符表示您正在访问对象属性。在这种情况下,属性名称应为mysql-5.4
,这是无效的PHP标识符(必须包含字母,数字或下划线,请参阅here)。因此,它100%确定已动态创建属性名称。
PHP允许使用名为__get()
的魔术方法重载属性。此方法的主体允许您处理您希望的任何属性 - 这可以是任何字符串,或任何变量,甚至是转换为字符串的对象。
所以在你的情况下,有人创建了一个带有__get()
魔术方法的类来处理字符串mysql-5.4
。给出大括号{
和}
表示该字符串应被视为属性名称(但是没有具有此名称的属性)。
答案 3 :(得分:2)
大括号语法允许您使用字符串文字或变量作为属性或方法名称。
这有几个原因:
(根据@ Deceze的回答):它允许您访问属于PHP语法无效的属性名称 - 例如,如果属性名称包含点或短划线,则根据您的示例。通常,这样的属性可以通过__get()
魔术方法访问,因为它们也是无效的语法,无法定义为类中的实际属性。
(按@ feela的回答):它允许您使用变量来引用您的属性。这类似于$$
变量语法。这通常不是很好的练习,但在某些情况下很有用。
(尚未提及任何其他答案):它允许您从代码中删除某些潜在的歧义。例如,请考虑以下代码:
$output = $foo->$bar['baz'];
这是含糊不清的。您可以通过添加大括号或括号来解决歧义:
$output = $foo->{$bar['baz']}; //gets the value of a property from $foo which has a name that is defined in $bar['baz']
$output = ($foo->$bar)['baz']; //gets the ['baz'] element of $foo->$bar array.
这一点尤其重要,因为即将发布的PHP 7将会改变代码的默认行为。这将使语言表现得更加一致,但会破坏没有大括号的现有代码。
另请参阅此更改的PHP文档:https://wiki.php.net/rfc/uniform_variable_syntax
但即使没有语言变化来强迫这个问题,这样的代码也应该有大括号来帮助提高可读性 - 如果你不戴括号,那么你最终可能会努力找出你想要做的事情当你在六个月后回到代码时。