为什么这种语法可以将关联数组值解析为字符串?

时间:2014-12-15 21:19:00

标签: php

我正在阅读codeacademy.com上的PHP课程,而高级阵列的第4/7课需要编写一个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编译器的行为吗?
  4. 如何准确地解析此语法?

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

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

1 个答案:

答案 0 :(得分:3)

这就是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

{}用于分隔ENTIRE数组/对象引用,强制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