PHP字符串插值语法

38

我尝试使用这个语法进行重定向:

header("location: readMore.php?id=$post['post_id']");

但是它没有起作用。只有在有人建议在$post['post_id']周围放置花括号后,它才起作用了!

正确的语法是:

header("location: readMore.php?id={$post['post_id']}");

在这种情况下,花括号做什么?


2
你尝试过像这样连接字符串吗?header("location: readMore.php?id=" . $post['post_id']); - JSLirola
1
不,但我现在尝试了一下,它确实可以工作。但是为什么我的语法不起作用,而这两个语法可以呢? - Pioneer2017
5个回答

61

引用手册

当在双引号或heredoc中指定string时,会解析其中的variables。有两种语法:simplecomplex。简单语法是最常见且方便的。它提供了一种嵌入变量、array值或object属性的方式,使得在string中能够轻松实现。使用花括号括起表达式的语法属于复杂语法。你的第一个代码采用了简单语法,而第二个代码采用了复杂语法。

手册并没有明确说明,但是简单语法中的空格似乎是一个错误,会使你的第一个代码无效。就我所见,复杂语法似乎支持与常规PHP相同的语法,但是似乎在任何地方也没有实际保证。

总的来说,字符串插值在一般情况下都比较不可靠:

$a = [['derp']];
$b = $a[0];

// Works. It prints derp
echo "$b[0]";

// Doesn't work. It throws an error
echo "$b[ 0 ]";

// Works. It prints derp
echo "{$b[ 0 ]}";

// Doesn't work. It prints Array[0]
echo "$a[0][0]";

// Works. It prints derp
echo "{$a[0][0]}";

// Doesn't work. It prints { Array[0] }
echo "{ $a[0][0] }";

你会在$object -> foo$object->foo->bar中遇到类似的问题。
对我来说,这纯粹是疯狂的。因此,我尽可能避免使用双引号字符串(我唯一使用它们的是转义序列,如"\n")。相反,我使用单引号和字符串连接,像这样:
header( 'location: readMore.php?id=' . $post[ 'post_id' ] );

这使你能够使用实际的PHP变量语法,而不需要恶劣的字符串插值功能。

34
字符串插值是一种语言特性,在合理使用时非常有用。相比于使用大量难看的引号和点号,我更喜欢使用长的插值字符串。 - Captain Hypertext
2
如果他们决定只允许一种语法,那么一切都会很好。例如,这个就会出错:$amount = 500; $str = "I have ${$amount} dollars" - Flame
9
这个回答至少三次表示插值很糟糕,但却没有给出原因。显然,将空格(或任何字符)放在错误的位置会导致错误。这不是一个语言特性不好的例子,而是你把字符放在不应该放的地方的例子。如果我在常规的非插值变量中间插入空格,它们也会出错。 - felwithe
8
@felwithe,你给出了一个关于为什么事情是这样的理由,但这并不能使它变得更好。我也不是说我能建造得更好,但这仍然不意味着它是合理的。 - Siguza
4
@Siguza:删除第一句话似乎起了很大的作用。在那之前,我读答案的方式可能被那个语句所影响,因为现在我不确定为什么当时会那么烦恼。抱歉! - Nerdmaster
显示剩余5条评论

6
我来到这个问题是为了更多地了解常量插值语法,当这些PHP "<<<" 用于创建称为 Heredocs 的多行字符串时(允许变量插值,与Nowdocs 不同)。

然而,似乎没有特定的语法,因此一个简单的解决方法是创建一个闭包来实现。在这里,它只是一个分配给变量的匿名函数,将使用参数调用:

$int = 'intruder';        // Variable
define('con', '"smart"'); // Constant
// For complex interpolation:
// 1. Define a closure (anonymous function)
// 2. Assign it to a variable with a short name (e.g.: _ )
// 3. Invoke the function by calling the variable with parameters enclosed in ()
$_ = function ($val){return $val;};

$doc = <<<TXT
Hi there,
One day I caught this $int nearby.
I was then told that actually other {$_(con)} $int was there before.
So who came first, the chicken or the egg?
TXT;                      // Heredoc
echo $doc;

输出:

你好,

有一天我在附近抓到了这个入侵者。

然后我被告知之前还有其他“聪明”的入侵者。

那么是鸡先生蛋先生先来呢?

您可以在3v4l在线测试。这是基于这个答案,并带有更多在插值括号内进行操作的示例


2
聪明。我已经验证了相同的技术在双引号字符串内也可以工作! - ToolmakerSteve

3

当你使用双引号或单引号时,PHP会把引号内的内容视为字符串,除非你告诉它这是一个变量。PHP将任何在 { 之后跟着 $ 的内容都视为变量并将其作为变量处理。以下是一个例子:

$Text = "XYz";
echo "name-{$Text}";

另一种可选方法是使用连接。以下是一个示例:
header("location: readMore.php?id=" . $post['post_id']);

6
由于PHP将双引号内的任何内容视为变量,如果在其前面加上"$",那么这个例子就很糟糕了。所以这段代码可以完美运行:echo "text: $text"; - junkfoodjunkie

2
括号允许PHP读取其中的内容作为变量。您也可以这样做:
header("location: readMore.php?id=" . $post['post_id']);

1
PHP的简单字符串内插不识别带引号的数组键,这正是你的示例完美展示了这一点。实际上,根据使用的语法方式不同,编写此代码的正确方式恰好相反: 简单语法与复杂语法。

简单语法 - 错误的写法

带引号的键无法解析。

header("location: readMore.php?id=$post['post_id']");

简单语法 - 正确

未使用引号的字符串是关联数组的键。

header("location: readMore.php?id=$post[post_id]");

复杂语法 - 错误

这段代码可以运行,但是仅当 post_id 是一个已定义的常量时才可以。否则,你会收到 PHP 的警告。

header("location: readMore.php?id={$post[post_id]}");

复杂语法 - 正确

与字符串外部的书写方式相同。

header("location: readMore.php?id={$post['post_id']}");

引用手册中关于复杂语法的内容:

// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";

如果使用带引号的键,我建议使用复杂(花括号)语法。你真的应该使用它们,因为在字符串插值之外,未加引号的键实际上是常量。很遗憾简单语法不允许它们存在,因为这会使代码审查和更新旧的PHP代码更加困难。


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