5

新しい PHP 7.0.0 が出たので、いわゆる「可変変数」の評価順序の変更が少し心配です。

このページの「変数処理の変更点」の下に、PHP 5 および PHP 7 での処理順序を含む式の例を示す表が表示されます。リストされている 4 つの式は次のとおりです。

$$foo['bar']['baz']
$foo->$bar['baz']
$foo->$bar['baz']()
Foo::$bar['baz']()

次の文字列と配列があるとします。

$qux = 'quux';
$foo = array('bar' => array('baz' => 'qux'));

表の最初の式は$$foo['bar']['baz']、PHP 5 では の値として名前が付けられた変数の値として解釈されます。$foo['bar']['baz']つまり、 の値$quxは です 'quux'

ただし、PHP 7 では、私が理解しているように、同じ式が の値として名前が付けられた変数として解釈され$fooます$foo

表の他の例は、これと同じテーマのバリエーションのようです。

もちろん、PHP 7 でこれが変更された理由 (具体的には、この変更が下位互換性よりも重要である理由) に興味がありますが、それは SO には適切な質問ではありません。私の質問はより実用的です:

この非互換性に対処するための推奨される方法は何ですか?

もちろん、問題のある式に中括弧を追加すると ( ${$foo['bar']['baz']}$foo->{$bar['baz']}$foo->{$bar['baz']}()およびFoo::{$bar['baz']}()) が役立ちますが、これは非常に面倒で、大量の古いコードを調べて、比較的少ない出現箇所を検索します...

そうでなければ、これらの 4 つの例は可能な唯一の構文のバリエーションですか? つまり、RegExp とgrep問題のあるすべてのコードを作成できますか? 他にどのようなバリエーションが存在する可能性がありますか?

4

4 に答える 4

5

Rasmus Lerdorf は、 Phan https://github.com/etsy/phanと呼ばれる、これらのいわゆる統一変数構文の問題を発見できる静的分析ツールを作成しました。

Phan には、-b, --backward-compatibility-checks潜在的な PHP 5 -> PHP 7 BC の問題をチェックするオプションがあります。

于 2015-12-04T16:33:08.150 に答える
0

ステップ1、問題表現を見つける

grep多くの要因があるため、魔法の正規表現を使用して見つけるのは非常に困難です。

Phan https://github.com/etsy/phan-b, --backward-compatibilityは、潜在的な PHP 5 -> PHP 7 BC の問題をチェックするオプションを使用して、それを解決できます。一般的な問題を探すので、少し重いかもしれません。

構成なしのツールが必要な場合は、試してみてください

PHP 移行 https://github.com/monque/PHP-Migration .

コードを 2 回解析します。最初は PHP 7、2 番目は PHP 5 です。次に、AST 結果のノードを比較し、違いが見つかった場合は、PHP 5/7 間で実行すると異なる動作が発生することを意味し、その行に移動できます。このツールによって報告され、コードを手動で確認します。

$ cat demo.php
<?php

$$foo['bar']['baz'];
$foo->$bar['baz'];
$foo->$bar['baz']();
Foo::$bar['baz']();

$ php bin/phpmig demo.php

File: demo.php
--------------------------------------------------------------------------------
Found 4 spot(s), 4 identified
--------------------------------------------------------------------------------
    3 | WARNING    | * | 7.0.0 | Different behavior between PHP 5/7
    4 | WARNING    | * | 7.0.0 | Different behavior between PHP 5/7
    5 | WARNING    | * | 7.0.0 | Different behavior between PHP 5/7
    6 | WARNING    | * | 7.0.0 | Different behavior between PHP 5/7
--------------------------------------------------------------------------------

ステップ 2、修正する

これで、修正する必要があるファイルと行番号を含むリストができました。

1、手動で修正し、慎重にテストすることをお勧めします

2, PHP-Parser PrettyPrinterでコード生成

<?php

use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter;

// Parse in PHP 5 mode
$parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP5);
$printer = new PrettyPrinter\Standard();

$code = <<<'EOC'
<?php

$$foo['bar']['baz'];
$foo->$bar['baz'];
$foo->$bar['baz']();
Foo::$bar['baz']();
EOC;

$stmts = $parser->parse($code);
$code = $printer->prettyPrintFile($stmts);
echo $code."\n";
于 2016-09-10T17:14:40.577 に答える
0

https://wiki.php.net/rfc/uniform_variable_syntax

手動でリファクタリングする以外に選択肢はありません。変数変数構文のすべての使用を見つけるための正規表現を考え出すことができない限り。

「なぜ」という理由について。統一された変数構文により、オブジェクト メソッドの「連鎖」を使用するのと同じ方法で、データ構造のプロパティ (配列インデックスや戻り値など) を使用できます。

可変変数の優先順位の変更は、この機能強化の犠牲者でした。私の意見では価値があります。

于 2015-12-04T16:13:18.910 に答える
0

コードを変換して、sedPHP7 の統一変数構文の問題を解決します

のすべてのインスタンスを見つけて$$、必要に応じて中括弧::$->$追加するだけです。

find . -name "*.php"  -exec grep -l '\->\$' {} \;|while read f; do
  echo $f;  grep -H '\->\$' $f ; 
  # do some sed magic here to add braces
done

find . -name "*.php"  -exec grep -l '\$\$\w*\[' {} \;|while read f; do 
  echo $f;  grep -H '\$\$\w*\[' $f ;
  # do some sed magic here to add braces
done

find . -name "*.php"  -exec grep -l '::\$' {} \;|while read f; do 
  echo $f;  grep -H '::\$' $f ;
  # do some sed magic here to add braces
done

誰かが正しい構文を知っているかもしれないsedので、ここに追加します。

&オブジェクトの前のポインターインスタンスを次のようにコメントアウトしました。

find . -name "*.php"  -exec grep -l new {} \;|while read f; do
  sed -i -e 's~=\s*\&\s*new~= /*\&*/ new~g' "$f">/tmp/a;
done

&後で発生する可能性のあるエラーを解決できるように、単に削除する代わりにコメントを追加しました。

于 2016-07-22T07:38:21.693 に答える