我正在开源一个包含魔法__call()
的特征。在测试期间,当使用特征的类的父类包含__call
方法时,我遇到了一个挑战。
trait SomeTrait {
public function __call($method, array $parameters) {
// ...
return parent::__call($method, $parameters);
}
}
这会导致致命错误:当前类范围没有父级时无法访问parent ::
我还尝试了以下其他一些answers:
return call_user_func_array([$this, '__call'], [$method, $parameters]);
这导致分段错误:11 。我想是因为一个无限的呼叫循环。
如何从特质的__call
方法中调用父{范围} __call
方法?
如果直接在特征中无法实现,那么我怎么能调用父__call
方法?
答案 0 :(得分:10)
请检查以下代码:
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
编辑:我认为这将涵盖所有可能性。
答案 1 :(得分:1)
这里的问题是,如果您在没有父级的类中使用此特征,则此调用将失败。在调用父函数之前,您可以考虑检查类是否具有父级。这可能是这样的:
@{ Html.RenderAction("SectionNavigation", "Base"); }
我还想说这可能不是最好的设计方法。我不认为类似于特性的东西,它应该是一个可移植的,可组合的功能集,应该是在采用类中改变/覆盖功能。继承链。