在特质

时间:2015-05-26 13:42:46

标签: php traits

问题

我正在开源一个包含魔法__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方法?

2 个答案:

答案 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"); }

我还想说这可能不是最好的设计方法。我不认为类似于特性的东西,它应该是一个可移植的,可组合的功能集,应该是在采用类中改变/覆盖功能。继承链。