PHP技巧|Null Coalesce的实例教程

147 阅读2分钟

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 的一个很好的理由。