1

Php は複数のクラスを拡張することをネイティブに許可していないため、行き詰まっています。laravel モデルを使用してデータを操作しており、2 つの異なるパッケージを使用してその機能を拡張したいと考えています。

Ardentバリデーターと更新履歴を保持するRevisionableを使用しようとしていますが、モデル内でこれら 2 つのクラスを拡張する方法がわかりません。

どんな助けでも大歓迎です。

4

3 に答える 3

1

私は最近、Revisionable をトレイトにするために多くの作業を行ってきました。

したがって、次のようにできますuse

class User extends Ardent {
    use \Venturecraft\Revisionable\RevisionableTrait;
}

現在開発ブランチにありますが、マスターにマージする前にテストするのを手伝ってください:

https://github.com/VentureCraft/revisionable/issues/36

[編集]これは master ブランチにあり、公開されています。

于 2014-02-25T05:54:20.723 に答える
1

ご存知のように、PHP は多重継承をサポートしていません。残念ながら、これは PHP の欠陥であり、熱心で改訂可能なパッケージ開発者によって引き起こされた問題です。Sentry を例にとると、必要な Eloquent の実装を使用できます。config.php で必要なものを設定するだけです。Laravel は、これらすべてのパッケージの基本クラスであるため、残念ながら手を結んでいません。私の意見では。

したがって、いくつかのオプションがあります。

1) 両方のパッケージの git リポジトリに問題を報告し、そのうちの 1 つが \Eloquent からの継承だけでなく、Eloquent モデルの抽象クラスを拡張するユーザーの任意のクラスからの継承をサポートするように変更されることを願っています。

これらのパッケージの 1 つのコードを変更して、プル リクエストをリポジトリに送信することもできます。それが良い変化であれば、おそらくそれが起こっているのを見るでしょう。

2)Eloquentから拡張されたクラスを作成し、両方のパッケージを依存関係として持ち、その内部でそれらのパッケージから必要なものを呼び出すことにより、リポジトリパターンを使用します。Eloquent は複雑なクラスであり、 を使用する場合__call()は、パッケージに転送する必要があるすべてのメソッドをマップする必要があるため、これは簡単なことではありません。そのため、Eloquent 独自の動的呼び出しを壊すリスクはありません。

use Ardent;
use Revisionable;

class User extends Eloquent {

    private $ardent;

    privave $revisionable;

    public function __construct(Ardent $ardent, Revisionable $revisionable)
    {
        $this->ardent = $ardent;

        $this->revisionable = $revisionable;
    }

    public function doWhatever() 
    {
        return $this->ardent->do();
    }

    public function __call($name, $arguments)
    {
        if($this->isArdentMethod($name))
        {
            return call_user_func_array(array($this->ardent,$name), $arguments);
        }
        else
        if($this->isRevisionableMethod($name))
        {
            return call_user_func_array(array($this->revisionable,$name), $arguments);
        }
        else
        {
            return parent::__call($name, $arguments);
        }
    }
}

この呼び出しに注意してください

return parent::__call($name, $arguments);

他のいずれかによって実行されることを意図していない場合、すべての呼び出しが Eloquent クラスにリダイレクトされるようにします。

実際のところ、メインクラスとして Ardent などのいずれかを選択することもできます。

class User extends Ardent {}

そして、依存関係として改訂可能にするだけです:

public function __construct(Revisionable $revisionable)

そして、注入された依存関係に改訂可能な呼び出しだけを転送します。結局、これらのクラスはすべて Eloquent であり、同じテーブルを指す多くの Eloquent モデルを持つことができるからです。

Revisionable ソース コードを見ると、本当に考えなければならない呼び出しは だけでsave()あることがわかります。これは Eloquent からオーバーライドされるためです。他のすべては Ardent のものを呼び出すことができます。

少し多すぎるように聞こえるかもしれませんが、実行可能です。

于 2014-02-22T16:55:11.537 に答える
0

おっしゃる通り、PHP は多重継承をサポートしていないため、多くのオプションはありません。それは醜いですが、魔法の方法を使用するこのようなものに頼る必要があるかもしれません.__call()

于 2014-02-22T16:37:54.120 に答える