2482kB | 5.1% |
|
テストによると、AST を使用した後、プログラムの全体的な実行時間は約 10% ~ 15% 改善されましたが、メモリ消費量も増加しました。この増加は、大きなファイルの 1 回のコンパイルでは明らかですが、実行中はそうではありません。プロジェクトの実行プロセス全体が非常に深刻な問題です。
また、上記の結果はすべて Opcache を使用していないことにも注意してください。運用環境で Opcache がオンになっている場合、メモリ消費量の増加は大きな問題ではありません。
セマンティックな変更
これが単なる時間の最適化である場合、AST を使用する十分な理由にはならないようです。実際、AST の実装は時間の最適化を考慮したものではなく、構文の問題を解決するために行われています。セマンティクスにおけるいくつかの変更を見てみましょう。
yield には括弧は必要ありません
PHP5 実装では、式コンテキスト (代入式の右側など) で yield
が使用される場合、 yield
宣言の両側で括弧を使用する必要があります:
<?php
$result = yield fn(); // 不合法的
$result = (yield fn()); // 合法的
この動作は、PHP5 の実装の制限によるものです。PHP7 では、括弧は必要ありません。したがって、次の記述方法も合法です。
<?php
$result = yield;
$result = yield $v;
$result = yield $k => $v;
もちろん、yield
のアプリケーション シナリオに従う必要があります。
括弧は動作に影響しません
PHP5 では、($foo)['bar'] = 'baz'
および $foo['bar'] = 'baz'
2 つのステートメントは異なる意味を持ちます。実は、前者の書き方は違法であり、次のようなエラーが発生します。
<?php
($foo)['bar'] = 'baz';
# PHP Parse error: Syntax error, unexpected '[' on line 1
しかし、PHP7 では、2 つの書き方は同じ意味になります。
同様に、関数のパラメータが括弧で囲まれている場合、型チェックに問題があります。この問題は PHP7 でも解決されています:
<?php
function func() {
return [];
}
function byRef(array &$a) {
}
byRef((func()));
上記のコードは、次の場合には警告しません。 ##byRef(func()) を使用しない限り、PHP5 では ##byRef(func())
が使用されますが、PHP7 では、func()
の両側に括弧があるかどうかに関係なく、次のエラーが発生します。
PHP の厳格な標準: 変数のみが参照によって渡される必要があります... list() の変更点 list キーワードの動作は大幅に変更されました。リストが変数に値を割り当てる順序 (等号の左右の順序) は、以前は右から左でしたが、現在は左から右です: <?php
list($array[], $array[], $array[]) = [1, 2, 3];
var_dump($array);
// PHP5: $array = [3, 2, 1]
// PHP7: $array = [1, 2, 3]
# 注意这里的左右的顺序指的是等号左右同时的顺序,
# list($a, $b) = [1, 2] 这种使用中 $a == 1, $b == 2 是没有疑问的。
上記の変更の理由は、PHP5 の代入プロセスでは、最初に 3 が配列に入力され、最後に 1 が入力されるためですが、順序が変更されたためです。 同じ変更は次のとおりです: <?php
$a = [1, 2];
list($a, $b) = $a;
// PHP5: $a = 1, $b = 2
// PHP7: $a = 1, $b = null + "Undefined index 1"
これは、前の代入プロセスで $b が最初に 2 を取得し、その後 $a の値が 1 になったためです。しかし、今回は $a が最初に変更されます。は 1 になり、配列ではなくなるため、$b は null になります。 list はオフセットごとに 1 回だけアクセスされるようになりました: <?php
list(list($a, $b)) = $array;
// PHP5:
$b = $array[0][1];
$a = $array[0][0];
// PHP7:
// 会产生一个中间变量,得到 $array[0] 的值
$_tmp = $array[0];
$a = $_tmp[0];
$b = $_tmp[1];
以前は特定の状況下でのみ空のリスト メンバーがすべて禁止されました: <?php
list() = $a; // 不合法
list($b, list()) = $a; // 不合法
foreach ($a as list()) // 不合法 (PHP5 中也不合法)
参照割り当ての順序PHP5 では参照割り当ての順序は右から左でしたが、現在は左から右です:<?php
$obj = new stdClass;
$obj->a = &$obj->b;
$obj->b = 1;
var_dump($obj);
// PHP5:
object(stdClass)#1 (2) {
["b"] => &int(1)
["a"] => &int(1)
}
// PHP7:
object(stdClass)#1 (2) {
["a"] => &int(1)
["b"] => &int(1)
}
__clone メソッドを直接呼び出すことができます## を直接使用できるようになりました。 #$obj->__clone() を使用して、__clone
メソッドを呼び出します。 __clone
は、以前は直接呼び出すことが禁止されていた唯一のマジック メソッドです。以前は、次のようなエラーが発生していました:
致命的エラー: オブジェクトに対して __clone() メソッドを呼び出すことができません - ' を使用してくださいclone $ obj' の代わりに...
変数構文の一貫性
AST は、別の RFC: https://wiki.php.net/rfc/ で提起されたいくつかの構文の一貫性の問題も解決します。 uniform_variable_syntax.
新しい実装では、以前の一部の文法表現の意味が現在のものと多少異なります。詳細については、次の表を参照してください:
#式
PHP5 | PHP7 |
##$$foo['bar']['baz'] |
${ $foo['bar']['baz']}
($$foo)['bar']['baz'] |
|
$foo-> ;$bar['baz'] |
$foo->{$bar['baz']}
($foo->$bar)[' baz'] |
|
$foo->$bar['baz']() |
$foo->{$bar['baz']}( )
($foo->$bar)['baz']() |
| ##Foo::$bar['baz']() | Foo:: {$bar['baz']}()
(Foo::$bar)['baz']() |
|
全体的には、以前の順序は右から左でしたが、現在は左から右です。また、括弧は動作に影響を与えないという原則に従います。このような複雑な変数の書き方は、実際の開発では注意が必要です。 |
関連する推奨事項:
php エラー エコー情報をオフにする 5 つの方法
php の FastCGI プロトコルソースコード分析