为什么 $foo[bar] 错了?
应该始终在用字符串表示的数组索引上加上引号。例如用
$foo['bar'] 而不是
$foo[bar]。但是为什么呢?可能在老的脚本中见过如下语法:
这样是错的,但可以正常运行。那么为什么错了呢?原因是此代码中有一个未定义的常量(
bar )而不是 string('bar'-注意引号)。而
PHP 可能会在以后定义此常量,不幸的是你的代码中有同样的名字。它能运行,是因为
PHP 自动将裸字符串(没有引号的 string
且不对应于任何已知符号)转换成一个其值为该裸 string 的
string。例如,如果没有常量定义为
bar,那么PHP 将在
string 中替代为 'bar' 并使用之。
警告
将未定义的常量当作裸字符串的回退会触发 E_NOTICE 级别错误。
从 PHP 7.2.0 起已废弃,并触发 E_WARNING 级别错误。
从 PHP 8.0.0 起被移除,并触发 Error 异常。
这并不意味着总是给键名加上引号。用不着给键名为
常量 或
变量 的加上引号,否则会使 PHP
不能解析它们。
示例 #17 Key Quoting
以上示例会输出:
检查 0:
Notice: Undefined index: $i in /path/to/script.html on line 9
坏的:
好的: 1
Notice: Undefined index: $i in /path/to/script.html on line 11
坏的:
好的: 1
检查 1:
Notice: Undefined index: $i in /path/to/script.html on line 9
坏的:
好的: 2
Notice: Undefined index: $i in /path/to/script.html on line 11
坏的:
好的: 2
演示此行为的更多例子:
示例 #18 More Examples
'apple', 'veggie' => 'carrot');// Correctecho $arr['fruit'], PHP_EOL; // appleecho $arr['veggie'], PHP_EOL; // carrot// Incorrect. This does not work and throws a PHP Error because// of an undefined constant named fruit//// Error: Undefined constant "fruit"try { echo $arr[fruit];} catch (Error $e) { echo get_class($e), ': ', $e->getMessage(), PHP_EOL;}// This defines a constant to demonstrate what's going on. The value 'veggie'// is assigned to a constant named fruit.define('fruit', 'veggie');// Notice the difference nowecho $arr['fruit'], PHP_EOL; // appleecho $arr[fruit], PHP_EOL; // carrot// The following is okay, as it's inside a string. Constants are not looked for// within strings, so no error occurs hereecho "Hello $arr[fruit]", PHP_EOL; // Hello apple// With one exception: braces surrounding arrays within strings allows constants// to be interpretedecho "Hello {$arr[fruit]}", PHP_EOL; // Hello carrotecho "Hello {$arr['fruit']}", PHP_EOL; // Hello apple// Concatenation is another optionecho "Hello " . $arr['fruit'], PHP_EOL; // Hello apple?>
// 这将不起作用,并会导致解析错误,例如:// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'// 这当然也适用于在字符串中使用超全局变量print "Hello $arr['fruit']";print "Hello $_GET['foo']";?>
和在 语法
一节中规定的一样,在方括号([” 和
“]”)之间必须有一个表达式。这意味着可以这样写:
这是一个用函数返回值作为数组索引的例子。PHP 也可以用已知常量,可能之前已经见过:
注意 E_ERROR 也是个合法的标识符,就和第一个例子中的
bar 一样。但是上一个例子实际上和如下写法是一样的:
因为 E_ERROR 等于 1,等等。
那么为什么这样做不好?
也许有一天,PHP 开发小组可能会想新增一个常量或者关键字,或者用户可能希望以后在自己的程序中引入新的常量,那就有麻烦了。例如已经不能这样用
empty 和 default 这两个词了,因为他们是
保留关键字。
注意:
重申一次,在双引号字符串中,不给索引加上引号是合法的因此
"$foo[bar]"
是合法的(“合法”的原文为 valid。在实际测试中,这么做确实可以访问数组的该元素,但是会报一个常量未定义的
notice。无论如何,强烈建议不要使用 $foo[bar]这样的写法,而要使用 $foo['bar']
来访问数组中元素。--haohappy 注)。至于为什么参见以上的例子和
字符串中的变量解析 中的解释。