成员 select 中未记录的行为更改和 PHP 中的数组索引优先级 7 - 这是一个错误吗?
Undocumented behavior change in member select and array index precedence in PHP 7 - is this a bug?
考虑以下程序,基于 Doctrine 1.2.3 中的 this 代码。
<?php
class C {
public function func($p) {
printf("In %s with param %s\n", __METHOD__, $p);
}
}
printf("PHP version %s\n", PHP_VERSION);
$callback = array('callback' => 'func', 'const' => 28);
$record = new C;
$repete = $callback['callback'];
$record->$repete(10);
$record->$callback['callback'](20);
如果我 运行 使用 PHP 版本 5.4.34,输出是:
$ /cygdrive/c/xampp1826/php/php.exe foo.php
PHP version 5.4.34
In C::func with param 10
In C::func with param 20
运行 PHP 7.4.12:
$ /cygdrive/c/xampp7412/php/php.exe foo.php
PHP version 7.4.12
In C::func with param 10
Notice: Array to string conversion in C:\cygwin64\home\repete\foo.php on line 12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
Notice: Undefined property: C::$Array in C:\cygwin64\home\repete\foo.php on line
12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
Notice: Trying to access array offset on value of type null in C:\cygwin64\home\
repete\foo.php on line 12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
Fatal error: Uncaught Error: Function name must be a string in C:\cygwin64\home\
repete\foo.php on line 12
Error: Function name must be a string in C:\cygwin64\home\repete\foo.php on line
12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
这是故意的不兼容更改还是错误?我没有看到它在版本 7 的不兼容更改中列出。这似乎是成员 select -> 和数组索引 [=29= 的相对优先级的问题][ ] 运算符。这个 notes that member select is not listed among the operators in the manual。我注意到也没有列出数组索引。
因此,如果手册没有指定优先级,是否意味着静默更改行为不是错误?行为改变本身,或者未能列出改变,肯定是一个错误。我是否错过了此更改被列为不兼容的更改?
我不知道 PHP 是哪个版本引入了更改,我只有 5.4.34 和 7.4.12 可供测试。
在@Ulrich Eckhardt 对原 post 的评论的推动下,我回去仔细阅读了 PHP 7.0 中关于向后不兼容更改的部分,并发现 this 及其 table 的旧评价和新评价:
Old and new evaluation of indirect expressions
Expression PHP 5 interpretation PHP 7 interpretation
$$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']()
table 中的第三行正是我在示例代码的第 12 行中遇到的问题。因此,我撤回了我的投诉,即这是一个未记录的更改。当然,我仍然可以抱怨很难在像 Doctrine ORM 这样的大型、强大的 PHP 库中找到这样的案例。但我想这就是我在 Doctrine 2 已经出现这么久的情况下继续使用 Doctrine 1 所付出的代价(大概 Doctrine 2 已经修复了任何 PHP 7 的不兼容性)。我会告诉自己去角落里坐下。
由于这基本上是语言解析方式的一种变化,因此可以想象,如果有可用的解析器实现,则可以相对简单地标记 PHP 7 解析的不同结构。有人知道这样的工具是否存在吗?我使用 RapidPHP 作为我的编辑器,以及用于调试的 netbeans,两者都有一些标记语法错误的功能,但没有人抱怨原始问题中的代码。
考虑以下程序,基于 Doctrine 1.2.3 中的 this 代码。
<?php
class C {
public function func($p) {
printf("In %s with param %s\n", __METHOD__, $p);
}
}
printf("PHP version %s\n", PHP_VERSION);
$callback = array('callback' => 'func', 'const' => 28);
$record = new C;
$repete = $callback['callback'];
$record->$repete(10);
$record->$callback['callback'](20);
如果我 运行 使用 PHP 版本 5.4.34,输出是:
$ /cygdrive/c/xampp1826/php/php.exe foo.php
PHP version 5.4.34
In C::func with param 10
In C::func with param 20
运行 PHP 7.4.12:
$ /cygdrive/c/xampp7412/php/php.exe foo.php
PHP version 7.4.12
In C::func with param 10
Notice: Array to string conversion in C:\cygwin64\home\repete\foo.php on line 12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
Notice: Undefined property: C::$Array in C:\cygwin64\home\repete\foo.php on line
12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
Notice: Trying to access array offset on value of type null in C:\cygwin64\home\
repete\foo.php on line 12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
Fatal error: Uncaught Error: Function name must be a string in C:\cygwin64\home\
repete\foo.php on line 12
Error: Function name must be a string in C:\cygwin64\home\repete\foo.php on line
12
Call Stack:
0.0005 403600 1. {main}() C:\cygwin64\home\repete\foo.php:0
这是故意的不兼容更改还是错误?我没有看到它在版本 7 的不兼容更改中列出。这似乎是成员 select -> 和数组索引 [=29= 的相对优先级的问题][ ] 运算符。这个
因此,如果手册没有指定优先级,是否意味着静默更改行为不是错误?行为改变本身,或者未能列出改变,肯定是一个错误。我是否错过了此更改被列为不兼容的更改?
我不知道 PHP 是哪个版本引入了更改,我只有 5.4.34 和 7.4.12 可供测试。
在@Ulrich Eckhardt 对原 post 的评论的推动下,我回去仔细阅读了 PHP 7.0 中关于向后不兼容更改的部分,并发现 this 及其 table 的旧评价和新评价:
Old and new evaluation of indirect expressions
Expression PHP 5 interpretation PHP 7 interpretation
$$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']()
table 中的第三行正是我在示例代码的第 12 行中遇到的问题。因此,我撤回了我的投诉,即这是一个未记录的更改。当然,我仍然可以抱怨很难在像 Doctrine ORM 这样的大型、强大的 PHP 库中找到这样的案例。但我想这就是我在 Doctrine 2 已经出现这么久的情况下继续使用 Doctrine 1 所付出的代价(大概 Doctrine 2 已经修复了任何 PHP 7 的不兼容性)。我会告诉自己去角落里坐下。
由于这基本上是语言解析方式的一种变化,因此可以想象,如果有可用的解析器实现,则可以相对简单地标记 PHP 7 解析的不同结构。有人知道这样的工具是否存在吗?我使用 RapidPHP 作为我的编辑器,以及用于调试的 netbeans,两者都有一些标记语法错误的功能,但没有人抱怨原始问题中的代码。