PHP中关联数组的插值(双引号字符串)

61

在使用 PHP 的字符串索引数组元素(5.3.3,Win32)进行插值时,可能会出现以下行为,也可能不会:

$ha = array('key1' => 'Hello to me');

print $ha['key1'];   # correct (usual way)
print $ha[key1];     # Warning, works (use of undefined constant)

print "He said {$ha['key1']}"; # correct (usual way)
print "He said {$ha[key1]}";   # Warning, works (use of undefined constant)

print "He said $ha['key1']";   # Error, unexpected T_ENCAPSED_AND_WHITESPACE
print "He said $ha[ key1 ]";   # Error, unexpected T_ENCAPSED_AND_WHITESPACE
print "He said $ha[key1]";     # !! correct (How Comes?)

有趣的是,最后一行似乎是正确的PHP代码。这个特性可信吗?


编辑:将现在的帖子重点设置为粗体字,以减少误解。


参见:https://stackoverflow.com/questions/27742321/how-to-echo-element-of-associative-array-in-string - dreftymac
4个回答

59

是的,你可以信任它。文档详细介绍了所有变量内插的方式

如果你想知道为什么会这样做,那我就无能为力了。但正如常言所说:PHP是一门古老的语言,并且已经发展了很多年,因此引入了不一致的语法。


@nikic,我在文档中找不到这个确切的情况(没有花括号),它在哪里?谢谢,rbo - rubber boots
2
@mario,我来自Perl(仍然在使用),在Perl中插值通常会使事情更易读。PHP中的DMF(非常想念的功能)是Perls q-operator(引用)系列-> qq {},q {},qx {},qw {}。因此(imho),字符串插值在PHP中可能不像它本应该的那样有用。 :-( - rubber boots
@rubber boots:嗯,PHP确实有 HEREDOCNOWDOC。虽然它们可能外观不那么美观,但它们通常具有相同的作用,不是吗? - NikiC
1
@nikic 有些服务,对吧。但不在一行上。 与Perl比较:$x = qq{<a href="$link">$text</a>}; - rubber boots
当你仔细想一想,这在抽象的层面上似乎是有道理的。当你有一个关联数组时,它期望一个字符串,现在整个变量名本身就已经被插值了进去,但在方括号内有更多引号将是多余的。让变量名在方括号内插值是有意义的,而方括号内的值不会被插值,除非它以美元符号开头。至少这是我对这个特性的解释,对我来说这似乎是合理的逻辑。 - Tory
显示剩余4条评论

20

是的,这是明确定义的行为,始终会查找字符串键 'key',而不是(可能未定义的)常量 key 的值。

例如,考虑以下代码:

$arr = array('key' => 'val');
define('key', 'defined constant');
echo "\$arr[key] within string is: $arr[key]";

这将输出以下内容:

$arr[key] within string is: val

虽然如此,编写这样的代码可能并不是最佳实践,而应该使用以下方式之一:

$string = "foo {$arr['key']}"
或者
$string = 'foo ' . $arr['key']

语法。


9
最后一个是PHP分词器处理的特殊情况。它不会查找是否定义了该名称的任何常量,它始终假定为字符串文字以与PHP3和PHP4兼容。

5
只针对那些感兴趣的人(可能没有人...):PHP将为数组索引生成一个T_STRING(如果它是非溢出十进制数,则为T_NUM_STRING),而不是通常的T_CONSTANT_ENCAPSED_STRING。请注意,此翻译仅供参考,不应视为正式文件。 - NikiC

0
回答你的问题,是的,PHP可以做到,并且与implode和explode一样,PHP非常宽容...因此不一致性很多。
我必须说我喜欢PHP的插值,因为它可以将基本的雏菊打印变量直接插入字符串中。
但是,如果您只使用单个数组对象进行字符串变量插值,则编写模板可能更容易,您可以将特定对象变量嵌入其中(例如在JavaScript或Python中),从而明确控制变量范围和应用于字符串的对象。
我认为这个人的isprintf对这种事情非常有用。

http://www.frenck.nl/2013/06/string-interpolation-in-php.html

<?php

$values = array(
    'who'   => 'me honey and me',
    'where' => 'Underneath the mango tree',
    'what'  => 'moon',
);

echo isprintf('%(where)s, %(who)s can watch for the %(what)s', $values);

// Outputs: Underneath the mango tree, me honey and me can watch for the moon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接