Home > Backend Development > PHP7 > body text

Teach you to use two lines of code to add a 'non-empty merge' syntactic sugar to PHP7

藏色散人
Release: 2023-02-17 15:02:01
forward
3453 people have browsed it

我们知道从 PHP 5.3 起三元运算符 ? : 有一个写法简洁写法是这样的:

<?php
$a = 0;
$b = $a ?: 1; # $b === 1
Copy after login

这实际上相当于:

<?php
$a = 0;
$b = $a ? $a : 1; # $b === 1
Copy after login

在 PHP5 中,语法分析是这样写的:

|   expr &#39;?&#39; { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
    expr &#39;:&#39; { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
    expr     { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
|   expr &#39;?&#39; &#39;:&#39; { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
    expr     { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
Copy after login

在 PHP7 中,由于 AST(抽象语法树)的引入,语法分析有些简化:

|   expr &#39;?&#39; expr &#39;:&#39; expr
        { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); }
|   expr &#39;?&#39; &#39;:&#39; expr
        { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
Copy after login

PHP7 中语法分析之后都是写到 AST 的节点上。从上面可以看出,简化的 ?: 和完整的三元表达式的区别就是节点中间的值为 NULL。

PHP7 添加了一个合并操作符(T_COALESCE),用于简化 isset 的条件判断:

<?php
$b = $a ?? 1;
Copy after login

它相当于:

<?php
$b = isset($a) ? $a : 1;
Copy after login

仅仅是 isset 判断,在 为等值时还是会返回b 的值还是为 0

这个操作符的语法分析语句是:

|   expr T_COALESCE expr
        { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }
Copy after login

如果想将 isset 换成 empty 的效果,也就是说在变量不存在或转换成 boolean 后为 false 都赋予其他值,需要这样写:

<?php
$b = $a ?? 1 ?: 1;
Copy after login

显然上面的表达式中中间一部分稍微有些多余,那么做些简化呢?

现在我想添加一个语法 ??: ,它的作用是对变量做 empty 的判断。也就是说达到上面 $a ?? 1 ?: 1 的效果:

<?php
$b = $a ??: 1;
Copy after login

改起来很简单,只需要将 ?: ?? 的分析合并一下(注意这里和上面所有的地方 $1 $2 等符号的数字表示的都是变量或者常量出现的位置顺序):

|   expr T_COALESCE &#39;:&#39; expr
        { $$ = zend_ast_create(ZEND_AST_CONDITIONAL,
            zend_ast_create(ZEND_AST_COALESCE, $1, $4), NULL, $4); }
Copy after login

仅仅只有两句,因为并没有在词法分析器中添加 Token,所以只能算是个语法糖。

重新编译一下之后就能看到效果啦。

测试:

$ /usr/local/php/bin/php -r "\$a = 0; echo \$a ?? 1, PHP_EOL;"
0
$ /usr/local/php/bin/php -r "\$a = 0; echo \$a ??: 1, PHP_EOL;"
1
Copy after login

The above is the detailed content of Teach you to use two lines of code to add a 'non-empty merge' syntactic sugar to PHP7. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template