这是PHP 5.4中关于通过引用传递对象的一个非常优秀的案例,其中获取此错误:
PHP Warning: Parameter 1 to A::foo() expected to be a reference, value given
Run Code Online (Sandbox Code Playgroud)
但仅作为复合效应:
不知道为什么这些东西都会导致这种行为或是否应该.
需要注意的是,PHP 5.5中不存在此效果.
这是导致上述错误的代码,但是如果你COMMENT THIS LINE对代码运行正常注释(例如,对象被正确传递给'foo'函数):
class A {
private function foo(&$arg1) {
var_dump('arg1: ', $arg1);
}
}
class B extends A {
public function bar() {
$x = new stdClass();
$x->baz = 'just a value';
$this->callPrivate($x);
}
private function callPrivate($x)
{
$method = new \ReflectionMethod(
'A',
'foo'
);
//* for some reason, the private function needs to have been changed to be 'accessible' for this to work in 5.4
$method->setAccessible(true);
//working 5.4 (* see above) but not in 5.5
$arguments = func_get_args();
//not working in either
$arguments = array($x); // <---- COMMENT THIS LINE TO SEE IT WORK IN PHP 5.4
return $method->invokeArgs($this, $arguments);
}
}
$y = new B();
$y->bar();
Run Code Online (Sandbox Code Playgroud)
我不明白为什么两个$ arguments数组之间会有任何区别,因为var_dumping它们显示相同的输出.因此,我认为这与较低级别的对象'指针'不同(我的深度在这里)?
另一个问题是,如果这是PHP 5.4,5.5或两者中的错误?
在 PHP 5.5.6 之前,func_get_args()从 VM 堆栈获取参数,复制它们并在数组中返回它们。PHP 5.5.6 中引入了一项优化,可以避免常见情况下这些昂贵的副本。不是复制 zval,而是仅增加引用计数(尽管有 by-ref args)。
通常这样的更改对用户代码的影响为零。但在引擎中的一些地方,可观察到的行为会根据 zval 的引用计数而有所不同。其中一个地方是按引用传递:
对于动态函数调用的情况,如果 zval 是引用或者具有 refcount==1 ,则可以通过引用传递 zval 。
在 PHP 5.5.6 之前,返回的数组中的 zvalfunc_get_args()始终具有 refcount==1,因此它们基于第二种情况进行处理。从 PHP 5.5.6 开始,这不再是正确的,因为按值 zval 的 refcount 总是>1,如果您尝试按引用传递它们,则会导致错误。
注意:该代码在 PHP 5.5.6 之前实际上不起作用(by-ref 被忽略)。这只是一个不幸的巧合,你没有收到错误提示;)
更新:由于 BC 中断,我们决定恢复 5.5 分支上的更改。您将在 PHP 5.5.8 中恢复旧行为,而新行为仅在 PHP 5.6 中出现。
| 归档时间: |
|
| 查看次数: |
351 次 |
| 最近记录: |