Blog Detail

  • PHP: Array 数组

    为什么 $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 注)。至于为什么参见以上的例子和

    字符串中的变量解析 中的解释。