PHP 7和8是该语言的巨大飞跃。在一个文件中黑掉整个Web应用程序的日子已经一去不复返了(尽管如果你觉得复古的话,技术上还是可以这么做的)。现在有这么多花哨的新语言功能,你可能会发现自己在变化的海洋中漂泊。
我想一次介绍其中的一些新特性,让它们有机会吸引你的注意力,抓住你的想象力。
今天的主题是:Null Coalesce操作符,这是PHP7.0中的一个小插曲,看起来像?? 。
为什么会有这个东西呢?
早在Ye PHP旧时代,在使用一个数组键之前检查它是否存在是一件非常频繁的事情,但也比它所需要的要啰嗦得多。
这里有几个例子(不要用它们,它们是故意做坏的!)。
<?php
// apply a default value to a form input
$input = null;
if (!empty($_POST['input'][1])) {
$input = $_POST['input'][1];
} else {
$input = 'default';
}
// detect a missing request parameter
if (array_key_exists($_REQUEST['subject'])) {
echo $_REQUEST['subject'];
} else {
echo 'Subject not found.';
}
// substitute an empty array when the body array is not provided
$myData = isset($_REQUEST['body']) ? $_REQUEST['body'] : array();
foreach ($myData as $row) {
echo $row;
}
如果没有这样的检查,PHP就会在日志中写一个通知。
你确实可以选择禁用Notice,让你的代码像一个穿着苏格兰服装的人在温柔的春风中自由地运行,但是......这很少是个好主意。
Null Coalesce操作符使你更容易给那个狡猾的苏格兰人穿上长裤。
它是如何工作的呢?
null凝聚运算符 (??) 是一个特殊的比较运算符,它读取其左边的值并使PHP做出决定。
- 如果左边的值是空的或者没有设置,PHP会替换掉操作符右边的值。
- 如果左边的值被设置且不是空值,则使用该值。
在某些情况下,前面的例子empty(),array_key_exists(), 和isset(), 可以用?? 来代替,这样代码更简洁。
<?php
// six lines become one
$input = $_POST['input'][1] ?? 'default';
// this one also cleans up nicely
echo $_REQUEST['subject'] ?? 'Subject not found.';
// this one, too
foreach ($_REQUEST['body'] ?? [] as $row) {
echo $row;
}
注意:所有这些带有
$_POST和$_REQUEST的例子都是危险的。它们作为语法演示可能还行,但在生产中运行这样的代码是很糟糕的。恶意的人可以注入各种令人讨厌的惊喜。考虑使用请求库和/或来自Composer/Packagist的验证库作为防止重大问题的方法。像Symfony和Laravel这样的PHP框架提供了内置的工具来保证你的用户和服务器的安全。
什么时候会引起问题?
Null coalesce有一个重要的怪癖,一开始可能很难让人理解。因为它是一个特殊的运算符,就像......悬空的东西一样在那里悬空。PHP对于什么是 "左边 "和 "右边 "会有一些古怪的看法。
这可能会导致糟糕的一天。
<?php
$var = null;
echo 'This is my ' . $var ?? 'output' . ' test';
echo "\n";
echo 'This is my ' . ($var ?? 'output') . ' test';
echo "\n";
// Output:
// ---------------------
// This is my
// This is my output test
在第一个例子中,我们很容易期望它只注意$var ,但事实并非如此。相反,PHP 决定检查的左侧实际上是一个包含"This is my " 的字符串,并将$var 的内容粘在最后。因为这永远不会是null ,所以字符串的最后部分永远不会被串联起来。
在这种情况下,添加小括号是非常必要的。 但是,并不是在所有情况下都需要这样做。请谨慎行事,并确保对你的代码进行单元测试。
在PHP7.4中还有一个奖励?
但是等等!还有更多!?还有呢!
PHP 7.4 引入了"Null Coalescing Assignment Operator",它将 Null Coalesce 操作符 (??) 与 Assignment 操作符 (=) 打成一个可爱的凯尔特结,从而产生了一个弹跳的婴儿??= 。
而不是像这样写一个恐怖的东西。
$myArray['subArray']['key'] = isset($myArray['subArray']['key'])
? $myArray['subArray']['key']
: 'default';
或者像这样。
$myArray['subArray']['key'] = $myArray['subArray']['key'] ?? 'default';
现在,你可以一次性地凝聚它和分配它。
$myArray['subArray']['key'] ??= 'default';
很好。如果我这么说的话,这也是升级到 PHP 7.4 的一个很好的理由。