php trait 特色の中のoverride magic methodからparent magic methodを呼び出す




trait parent method (2)

問題

私はマジックメソッド__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]);

これにより、 セグメンテーション違反が発生します 。 無限の呼び出しループがあると思います。

質問

特性の__callメソッド内から親の__callメソッドを呼び出す方法を__callください。

特性内から直接実行できない場合、それ以外の方法で親の__callメソッドを呼び出す方法はありますか。


ここで問題となるのは、親なしのクラスでこのトレイトを使用すると、この呼び出しが失敗するということです。 親関数を呼び出す前に、クラスに親があるかどうかを確認することを検討してください。 それはこのように見えるかもしれません:

trait SomeTrait {
    public function __call($method, array $parameters) {
        // ...
        if (count(class_parents($this)) {
            return parent::__call($method, $parameters);
        }
    }
}

私はまたこれが最善の設計アプローチではないかもしれないと言うでしょう。 移植可能で構成可能な一連の機能を提示することになっているトレイトのようなものが、採用クラスの継承チェーンの機能を変更またはオーバーライドするべきではないと思います。


下記のコードを確認してください。

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 : http://3v4l.org/R8hI3

編集:これはすべての可能性をカバーすると思います。





traits