PHP的简化运算符

前言

最近在尝试做代码review,期间遇到了很多有趣的操作符。问题来了,写了这么多年的PHP语言,你对常见的简化运算符熟悉吗?我们一起来看看常见运算符吧。

三元运算符 ?:

在很多地方,我们会尝试使用三元运算符来简化代码,减少if的编写。对程序员来说,少敲一行代码,也是节省时间的。个人认为三元运算符最直接的作用是可以直接把多行代码简化为一行。

// 通常的写法
if (empty($_POST['action'])) {
    $action = 'default';
} else {
    $action = $_POST['action'];
}
// 使用三元运算符,只需要一行
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

甚至三元运算符也可以使用简写的方式,但仅用在判断条件为表达式或者变量,如果是为isset这类bool时,只能应用在返回bool值。

// 简写
return true?:false;
// 表达式
$test1="test1";
$test3="test3";
// 返回test1
return $test1?:$test3;
// 返回test3
$test1=false;
return $test1?:$test3;
// 返回bool
$a = true;
return isset($a)?:'isset';

空值合并运算符 ??

在PHP的7.0版本里,为了解决isset在三元运算符的语法冗余问题,PHP又添加一个新操作符??。它是这样使用的。

$username = $_GET['user'] ?? 'nobody';
// 等同于下面的代码
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// 另外的例子
$model = Model::get($id) ?? $default_model;
// 等同于下面的代码
if (($model = Model::get($id)) === NULL) { $model = $default_model; }
// 再举一个例子
$imageData = json_decode(file_get_contents('php://input'));
$width = $imageData['width'] ?? 100;
// 等同于
$width = isset($imageData['width']) ? $imageData['width'] : 100;

空值合并赋值运算符 ??=

在解决上面的isset的判断问题后,发现有一些代码写起来还是很冗余。比如下面的代码。

// 例子
$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';

没办法,为了写更少的代码,php开发组在PHP7.4添加新的赋值运算符??=。

// 简写
$this->request->data['comments']['user_id'] ??= 'value';

你看又一个语法糖诞生了,它并没有改变什么本质的东西,只是你要写的代码更少了。

组合比较运算符 <=>

像上面这类运算符,在7.0的版本也有,比如<=>。有时候,我们只是简单的想要知道两个变量的比较结果而已。

新运算符 (expr) <=> (expr),如果两边相等,就返回0,左边大于右边就返回1,右边大于左边就返回-1。

以下是该运算符其行为的示例:

// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1

// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1

echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1

// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1

// Objects
$a = (object) ["a" => "b"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 0

$a = (object) ["a" => "b"]; 
$b = (object) ["a" => "c"]; 
echo $a <=> $b; // -1

$a = (object) ["a" => "c"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 1

$a = (object) ["a" => "b"]; 
$b = (object) ["b" => "b"]; 
echo $a <=> $b; // 0

该运算符与常用比较运算法 <, <=, ==, >= and >的比较如下:

operator <=> equivalent
$a < $b ($a <=> $b) === -1
$a <= $b ($a <=> $b) === -1 || ($a <=> $b) === 0
$a == $b ($a <=> $b) === 0
$a != $b ($a <=> $b) !== 0
$a >= $b ($a <=> $b) === 1 || ($a <=> $b) === 0
$a > $b ($a <=> $b) === 1

箭头函数第二版 =>

PHP在5.3的版本添加了闭包函数,你可以像下面这样来写闭包函数:

function array_values_from_keys($arr, $keys) {
    return array_map(function ($x) use ($arr) { return $arr[$x]; }, $keys);
}

看起来,写的代码有点多,有没有优化的空间呢?当然有,PHP在7.4版本优化了箭头函数,你可以像ES6一样编写箭头函数:

// 感觉少写很多代码
function array_values_from_keys($arr, $keys) {
    return array_map(fn($x) => $arr[$x], $keys);
}
// 举例
$y = 1;
$fn2 = function ($x) use ($y) {
    return $x + $y;
};
// 箭头函数
$y = 1;
$fn1 = fn($x) => $x + $y;
// 嵌套也是可以的
$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;

解参数数组表达式 …

PHP为了”进一步”解放你的生产力,在7.4的版本还添加了和ES6类似的解参数运算符,但目前只能应用在数组里。

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// 你得到一个新的数组 ['banana', 'orange', 'apple', 'pear', 'watermelon'];
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]

平方运算符

最后,我甚至还在rfc发现平方运算符(从5.6起就可以使用),这下又少调用一个函数了。

echo 2 ** 3; // 8
$x = 2;
$x **= 3;
echo $x; // 8
// 支持GMP
$base = gmp_init(2);
$exponent = 3;
var_dump($base ** $exponent);

// output
object(GMP)#3 (1) {
  ["num"]=>
  string(1) "8"
}

总结

文章总结目前PHP最新版本支持的7个运算符,其本质就是语法糖,让你可以少写很多冗余的代码,让你的代码读起来简单。

但语法糖毕竟是糖,在吃的过程中很甜,甜完过后,并没有什么本质上改变。

其实我更希望能看到更多的”干货”。

参考链接

  1. 三元运算符 Ternary Operator
  2. 空值合并运算符 Null Coalesce Operator
  3. 空值合并赋值运算符 Null Coalescing Assignment Operator
  4. 组合比较运算符 Combined Comparison (Spaceship) Operator
  5. 箭头函数 v2Arrow Functions 2.0
  6. 解参数数组表达式 Spread Operator in Array Expression
  7. 平方运算符 Power Operator

“PHP的简化运算符”的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注