为什么此语法可用于将关联数组值解析为字符串


Why does this syntax work to parse an associative array value into a string?

我正在 codeacademy.com 和高级数组的第 4/7 课上学习 PHP 课程,想要编写一个从关联数组访问值的 echo 语句。

我的第一次尝试是:

echo "I own a $myAssocArray['colour'] $myAssocArray['doors']-door $myAssocArray['year'] $myAssocArray['make'].";

抛出错误:

解析错误:语法错误、意外T_ENCAPSED_AND_WHITESPACE、第 26 行出现T_STRING或T_VARIABLE或T_NUM_STRING

意识到我可以使用连接运算符来做到这一点:

echo "I own a " . $myAssocArray['colour'] . " " . $myAssocArray['doors'] . "-door " . $myAssocArray['year'] . " " . $myAssocArray['make'] . ".";

在玩的时候,我只需删除数组访问器中的撇号就可以工作。下面的编译没有错误,并生成预期的字符串:

echo "I own a $myAssocArray[colour] $myAssocArray[doors]-door $myAssocArray[year] $myAssocArray[make].";

我还可以使用大括号表示法以我认为需要的方式访问数组值:

echo "I own a {$myAssocArray['colour']} {$myAssocArray['doors']}-door {$myAssocArray['year']} {$myAssocArray['make']}.";

我的理解是关联数组值可以通过索引(整数(或键(字符串(访问。

  1. 我的理解有误吗?
  2. 还是有什么我没把握的基本原则?
  3. 或者这是特定于 codeacademy.com 使用的 PHP 编译器的行为?

如何准确解析此语法?

echo "some text $associative_array[key] some more text";

编译器如何知道将key(或colourdoorsmakeyear等(解释为字符串值?

这就是PHP的方式,一致性是一种致命的罪过:

    双引号
  • 字符串中的数组键不能用引号引起来,除非它们在{}嵌入语法中。
  • 双引号字符串中的多维数组/对象以非贪婪的方式解析,这就是为什么有{}扩展字符串语法的原因。

考虑:

$foo['bar']['baz'] = 'qux'; // a simple 2 layer array

显而易见的一点:

echo "Hello, $foo['bar']['baz']" // error: t_encapsed_and_whitespace

快速破解修复,删除引号:

echo "Hello, $foo[bar][baz]" // outputs: Hello, Array[baz]

它实际上是解析/执行的:

echo "Hello, ";    // plain string
echo $foo['bar'];  // array in string context, which will print as the word "Array"
echo "[baz]";      // Another plain string

由于PHP的解析器并不贪婪,它在FIRST ]之后停止,认为这是数组的结束。因此,您的"上层"数组被转换为字符串,从而产生字面单词 Array ,而数组键业务的其余部分仅被视为纯文本。

输入扩展语法:

echo "Hello, {$foo['bar']['baz']}"; // Outputs: Hello, qux

{}用于分隔整个数组/对象引用,迫使 PHP 将所有[]块视为键。由于您现在处于特殊的"数组/字符串中的对象"模式,因此数组键必须再次用引号括起来。

对于对象,也会发生同样的事情:

$foo->bar->baz = 'qux'; 
echo "Hello, $foo->bar->baz";

然后导致"stdclass 的对象无法转换为字符串",因为它被解析/执行为:

echo "Hello, ";
echo $foo->bar;
echo "->baz"; 

除非 bar 子对象实现魔术__toString()方法,否则会发生"无法转换"错误。但无论如何,放入{}符号使其有效">

echo "Hello, {$foo->bar->baz}"; // outputs: Hello, qux