我們知道從 PHP 5.3 起三元運算符 ? : 有一個寫法簡潔寫法是這樣的: <?php $a = 0; $b = $a ?: 1; # $b 1 這實際上相當於: <?php $a = 0; $b = $a ? $a : 1; # $b 1 在 PHP5 中,語法分析是這樣寫的: | expr ...
我們知道從 PHP 5.3 起三元運算符 ? :
有一個寫法簡潔寫法是這樣的:
<?php $a = 0; $b = $a ?: 1; # $b === 1
這實際上相當於:
<?php $a = 0; $b = $a ? $a : 1; # $b === 1
在 PHP5 中,語法分析是這樣寫的:
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); } | expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); } expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
在 PHP7 中,由於 AST(抽象語法樹)的引入,語法分析有些簡化:
| expr '?' expr ':' expr { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); } | expr '?' ':' expr { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
PHP7 中語法分析之後都是寫到 AST 的節點上。從上面可以看出,簡化的 ?: 和完整的三元表達式的區別就是節點中間的值為 NULL。
PHP7 添加了一個合併操作符(T_COALESCE),用於簡化 isset
的條件判斷:
<?php $b = $a ?? 1;
它相當於:
<?php $b = isset($a) ? $a : 1;
僅僅是 isset
判斷,在 為等值時還是會返回b
的值還是為 0
。
這個操作符的語法分析語句是:
| expr T_COALESCE expr { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }
如果想將 isset
換成 empty
的效果,也就是說在變數不存在或轉換成 boolean
後為 false
都賦予其他值,需要這樣寫:
<?php $b = $a ?? 1 ?: 1;
顯然上面的表達式中中間一部分稍微有些多餘,那麼做些簡化呢?
現在我想添加一個語法 ??:
,它的作用是對變數做 empty
的判斷。也就是說達到上面 $a ?? 1 ?: 1
的效果:
<?php $b = $a ??: 1;
改起來很簡單,只需要將 ?:
和 ??
的分析合併一下(註意這裡和上面所有的地方 $1 $2
等符號的數字表示的都是變數或者常量出現的位置順序):
| expr T_COALESCE ':' expr { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, zend_ast_create(ZEND_AST_COALESCE, $1, $4), NULL, $4); }
僅僅只有兩句,因為並沒有在詞法分析器中添加 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
更多學習內容請訪問:
騰訊T3-T4標準精品PHP架構師教程目錄大全,只要你看完保證薪資上升一個臺階(持續更新)