从特征中的覆盖魔法方法调用父魔法方法
Call parent magic method from override magic method in a trait
问题
我正在开源一个包含魔术方法 __call()
的特性。在测试过程中,当使用特征的 class 的父 class 包含 __call
方法时,我遇到了挑战。
我试过的
trait SomeTrait {
public function __call($method, array $parameters) {
// ...
return parent::__call($method, $parameters);
}
}
这会导致致命错误:无法访问父级::当前class范围没有父级
我还尝试了以下,基于其他answers:
return call_user_func_array([$this, '__call'], [$method, $parameters]);
这会导致 分段错误:11。我想是因为无限调用循环。
问题
如何从特征的 __call
方法中调用父的 __call
方法?
如果不能直接从 trait 内部调用,否则我如何调用父级的 __call
方法?
请检查以下代码:
trait SomeTrait
{
public function __call($method, array $parameters)
{
// ...
return is_callable(['parent', '__call']) ? parent::__call($method, $parameters) : null;
}
}
class GreatParentClass
{
public function __call($method, array $parameters)
{
return 'bar';
}
}
class ParenClassWithoutCall
{
}
class ProxyClass extends GreatParentClass
{
}
class FooClass extends ProxyClass
{
use SomeTrait;
}
class BarClass extends GreatParentClass
{
use SomeTrait;
}
class BazClass extends ParenClassWithoutCall
{
use SomeTrait;
}
class SomeClassWithoutParent
{
use SomeTrait;
}
$class = new FooClass();
var_dump($class->foobar());
$class = new BarClass();
var_dump($class->foobar());
$class = new BazClass();
var_dump($class->foobar());
$class = new SomeClassWithoutParent();
var_dump($class->foobar());
这将打印:
string(3) "bar"
string(3) "bar"
NULL
NULL
带有要检查的代码的沙盒:
http://3v4l.org/R8hI3
编辑:我认为这将涵盖所有可能性。
这里的问题是,如果您在没有父项的 class 中使用此特征,则此调用将失败。您可以考虑在调用父函数之前检查 class 是否有父函数。这可能看起来像这样:
trait SomeTrait {
public function __call($method, array $parameters) {
// ...
if (count(class_parents($this)) {
return parent::__call($method, $parameters);
}
}
}
我还要说这可能不是最好的设计方法。我不认为像 trait 这样的东西,它应该提供一组可移植的、可组合的功能,应该是采用 class' 继承链中的 changing/overriding 功能。
问题
我正在开源一个包含魔术方法 __call()
的特性。在测试过程中,当使用特征的 class 的父 class 包含 __call
方法时,我遇到了挑战。
我试过的
trait SomeTrait {
public function __call($method, array $parameters) {
// ...
return parent::__call($method, $parameters);
}
}
这会导致致命错误:无法访问父级::当前class范围没有父级
我还尝试了以下,基于其他answers:
return call_user_func_array([$this, '__call'], [$method, $parameters]);
这会导致 分段错误:11。我想是因为无限调用循环。
问题
如何从特征的 __call
方法中调用父的 __call
方法?
如果不能直接从 trait 内部调用,否则我如何调用父级的 __call
方法?
请检查以下代码:
trait SomeTrait
{
public function __call($method, array $parameters)
{
// ...
return is_callable(['parent', '__call']) ? parent::__call($method, $parameters) : null;
}
}
class GreatParentClass
{
public function __call($method, array $parameters)
{
return 'bar';
}
}
class ParenClassWithoutCall
{
}
class ProxyClass extends GreatParentClass
{
}
class FooClass extends ProxyClass
{
use SomeTrait;
}
class BarClass extends GreatParentClass
{
use SomeTrait;
}
class BazClass extends ParenClassWithoutCall
{
use SomeTrait;
}
class SomeClassWithoutParent
{
use SomeTrait;
}
$class = new FooClass();
var_dump($class->foobar());
$class = new BarClass();
var_dump($class->foobar());
$class = new BazClass();
var_dump($class->foobar());
$class = new SomeClassWithoutParent();
var_dump($class->foobar());
这将打印:
string(3) "bar"
string(3) "bar"
NULL
NULL
带有要检查的代码的沙盒: http://3v4l.org/R8hI3
编辑:我认为这将涵盖所有可能性。
这里的问题是,如果您在没有父项的 class 中使用此特征,则此调用将失败。您可以考虑在调用父函数之前检查 class 是否有父函数。这可能看起来像这样:
trait SomeTrait {
public function __call($method, array $parameters) {
// ...
if (count(class_parents($this)) {
return parent::__call($method, $parameters);
}
}
}
我还要说这可能不是最好的设计方法。我不认为像 trait 这样的东西,它应该提供一组可移植的、可组合的功能,应该是采用 class' 继承链中的 changing/overriding 功能。