我正在 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']}.";
我的理解是关联数组值可以通过索引(整数(或键(字符串(访问。
- 我的理解有误吗?
- 还是有什么我没把握的基本原则?
- 或者这是特定于 codeacademy.com 使用的 PHP 编译器的行为?
如何准确解析此语法?
echo "some text $associative_array[key] some more text";
编译器如何知道将key
(或colour
、doors
、make
、year
等(解释为字符串值?
这就是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