PHP operator ->{...} 是什么意思?

What does PHP operator ->{...} mean?

我最近在 PHP 一段代码中看到了这一行:

$dbObject = json_decode($jsonString);
$dbObject->{'mysql-5.4'}[0]->credentials

这是什么意思?在 PHP docs 中我们可以读到

Both square brackets and curly braces can be used interchangeably for accessing array elements (e.g. $array[42] and $array{42} will both do the same thing in the example above).

但是如何定义对象 $dbObject 以允许 ->{...}[...]访问?这段代码有点不安全吗?哪个 PHP 版本允许这样做?

我是否遗漏了 PHP 文档中的任何内容?

它是为了允许访问那些将是无效语法的属性作为裸文字。含义:

$dbObject->mysql-5.4[0]->credentials

这是 invalid/ambiguous 语法。要向 PHP 表明 mysql-5.4 是 属性 而不是 属性 减去浮点数,您需要使用 {'..'} 语法。

确切地说,->{..} 允许您使用任何 表达式 作为 属性 名称。例如:

$dbObject->{ sprintf('%s-%.1f', 'mysql', 5.4) }

示例中的花括号语法不是来自数组语法,而是来自使用变量名访问变量的可能语法。

Curly braces may also be used, to clearly delimit the property name. They are most useful when accessing values within a property that contains an array, when the property name is made of mulitple parts, or when the property name contains characters that are not otherwise valid (e.g. from json_decode() or SimpleXML).

PHP 文档中的示例:

echo $foo->{$baz[1]} . "\n";
echo $foo->{$start . $end} . "\n";
echo $foo->{$arr[1]} . "\n";

参见“PHP可变变量”:http://php.net/manual/en/language.variables.variable.php (那里有更多关于用法的例子……)

作为 的补充:

-> 运算符意味着您正在访问一个对象 属性。在这种情况下,属性 名称应该是 mysql-5.4,这是无效的 PHP 标识符(它必须包含字母、数字或下划线,请参阅 here)。所以可以 100% 确定 属性 名称是动态创建的。

PHP 允许使用名为 __get() 的魔术方法重载属性。此方法的主体允许您处理任何您希望的 属性 - 这可以是任何字符串或任何变量,甚至是一个对象,它被转换为字符串。

所以在你的情况下,有人创建了一个 class 和一个 __get() 魔术方法来处理字符串 mysql-5.4。花括号 {} 表示该字符串应被视为 属性 名称(但是没有 属性 具有此名称)。

大括号语法允许您使用字符串文字或变量作为 属性 或方法名称。

这很有用,原因如下:

  1. (根据@Deceze 的回答):它允许您访问 属性 否则无效 PHP 语法的名称——例如,如果 属性根据您的示例,名称包含一个点或破折号。通常像这样的属性可以通过 __get() 魔术方法访问,因为它们也是无效语法,无法定义为 class.

    [=37 中的实际 属性 =]
  2. (根据@feela 的回答):它允许您使用变量来引用您的属性。这类似于 $$ variable 变量语法。这通常不是很好的做法,但在某些情况下很有用。

  3. (尚未被任何其他答案提及):它允许您从代码中消除某些潜在的歧义。例如考虑以下代码:

    $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

    但即使没有更改语言来强制解决这个问题,像这样的代码也应该有大括号来帮助提高可读性——如果你不加大括号,那么你最终可能会难以理解你正在尝试的内容当您在六个月后返回代码时要做的事情。