Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
变量处理顺序:PHP7中的更改_Php_Migration_Incompatibility_Variable Variables_Php 7 - Fatal编程技术网

变量处理顺序:PHP7中的更改

变量处理顺序:PHP7中的更改,php,migration,incompatibility,variable-variables,php-7,Php,Migration,Incompatibility,Variable Variables,Php 7,随着新的PHP7.0.0的推出,我有点担心所谓“变量”的计算顺序的变化 在上,在“变量处理的更改”下,将显示一个表,其中包含表达式的示例及其在PHP5和PHP7中的处理顺序。列出的四个表达式是: $$foo['bar']['baz'] $foo->$bar['baz'] $foo->$bar['baz']() Foo::$bar['baz']() 给定以下字符串和数组: $qux = 'quux'; $foo = array('bar' => array('baz' =>

随着新的PHP7.0.0的推出,我有点担心所谓“变量”的计算顺序的变化

在上,在“变量处理的更改”下,将显示一个表,其中包含表达式的示例及其在PHP5和PHP7中的处理顺序。列出的四个表达式是:

$$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
的值

然而,据我所知,在PHP7中,相同的表达式将被解释为
$foo
中名为值的变量,因此我希望得到“数组到字符串转换”的PHP通知,因为
$foo
是一个数组

表中的其他示例似乎是同一主题的变体

当然,我很好奇为什么PHP7会改变这一点(具体来说,为什么这一改变比向后兼容更重要),但是,这不是一个合适的问题。我的问题更切合实际:

处理这种不兼容的建议方法是什么?

当然,在有问题的表达式中添加大括号会有所帮助(
${$foo['bar']['baz']}
$foo->{$bar['baz']}
$foo->{$bar['baz']}()
foo:{$bar['baz']}()
),但这非常麻烦,要遍历大量的旧代码,搜索相对较少的事件

否则,这四个示例是唯一可能的语法变体吗?也就是说,我可以创建一个RegExp和
grep
所有有问题的代码吗?可能存在哪些其他变体?

你真的别无选择,只能手工重新考虑它们。除非你能想出一个正则表达式来找出所有变量语法的用法

关于“为什么”。统一变量语法允许我们像使用对象方法的“链接”一样使用数据结构的属性(如数组索引和返回值)


对可变优先顺序的更改是这种增强的牺牲品。在我看来,这是值得的。

Rasmus Lerdorf编写了一个静态分析工具,可以发现这些所谓的统一变量语法问题,称为Phan

Phan有选项
-b,--backward compatibility checks
来检查潜在的PHP5->PHP7BC问题。

使用
sed转换代码来解决PHP7统一变量语法问题
您只需找到
$
:$
->$
的所有实例,并在需要时添加大括号:

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

我添加了注释,而不是仅仅删除
&
,以便能够解决以后可能出现的错误。

步骤1,查找问题表达式

使用
grep
和一些神奇的正则表达式很难找到它,因为它有很多因素

Phan可以解决这个问题,使用选项
-b,--backwardcompatibility
检查潜在的PHP5->PHP7BC问题。它可能有点重,因为它寻找共同的问题

如果你想要一个没有配置的工具,你可以试试

PHP迁移

它将两次解析代码,第一次解析为PHP7,第二次解析为PHP5。然后比较AST结果中的节点,如果发现任何差异,则意味着它在PHP5/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
--------------------------------------------------------------------------------
$cat demo.php

真的那么麻烦吗?您只需要找到
$
->$
的所有实例,并在需要的地方添加大括号。如果您有比
$$foo
更复杂的多个实例,那么您的代码还是有问题。认为这是一个重构的机会。另外,如果你有良好的测试,那么你甚至不需要这样做。看看哪些测试在5.x下失败,哪些测试在7下通过。然后修复您的代码。谢谢Ed Cottrell,您认为只有
$$
->$
:$
可以查看吗?我还想念哪些人?(我能处理假阳性,那些不太多)。可能会为您确定UV问题,以及其他各种可能的迁移hiccups@MartenKoetsier应该这样做。请注意,
::$
将给您带来很多误报,相对于其他错误。另外,仅供参考,如果您使用PHPStorm(或想尝试演示),PHPStorm 10会自动执行大量PHP7兼容性检查。(我没有隶属关系;我只是喜欢这个产品。)不幸的是,Phan需要PHP7+,我还不容易获得它(现在!)。但是,我在他们的源代码中查找了兼容性检查,只找到了对
$$var[]
$foo->$bar['baz']的引用(都在函数
visitDim
中的src/Phan/Analyze/BreadthFirstVisitor.php中)。这些是指测试0047和0051。这让我想到搜索
$$
->$
(@Ed Cottrell)确实会奏效!我也在寻找其他的检测手段,但没有积极的结果。也许将来会有一些轻量级的解析器可用。同时,你的回答至少帮助解决了我的问题,所以现在,它被接受了。谢谢,谢谢你的链接。阅读这篇文章有助于我更好地理解它。“为什么”的问题至少得到了回答!最后,我可能真的会手工重构。这方面的主要问题是寻找实例,这可能通过来自Phan的测试得到充分解决。
<?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";