3

私は、MVCの原則に従って動作し、依存性注入を利用するPHPフレームワークの構築に取り組んでいます。フロントコントローラーの部分が下がっていると思います。コントローラインスタンスをインスタンス化し、要求されたURIに基づいて適切なアクションを呼び出す動作中のルータがあります。

次は依存性注入です。リフレクションを使用して依存関係を解決するコンテナを実装したいと思います。そうすることで、コントローラーに問題が発生していると思います。

派生コントローラークラスで使用できるようにする必要がある、私が「システム依存関係」と呼ぶものがいくつかあります。私はまだこれらすべての依存関係を実際に作成していませんが、コントローラーがInputProvider(get / postパラメーターまたはコマンドライン引数をカプセル化するため)などのサービスにアクセスできること、そしておそらく出力依存関係にアクセスできることは賢明なようです。理想的には、フレームワークのコンテナーを使用して、これらの依存関係をコントローラーのコンストラクターに注入しますが、ここで問題が発生します。

コントローラーのシステム依存関係にコンストラクターインジェクションを使用する場合、派生コントローラーがそれ自体のコンストラクターを実装している場合は、ベースコントローラーの依存関係を管理するように強制します。それは最もユーザーフレンドリーではないようです。もう1つのオプションは、システムの依存関係にセッターインジェクションを使用することですが、派生コントローラーは、コンストラクターで必要な場合、これらのシステムの依存関係にアクセスできません。

両方の長所を提供する唯一の解決策は、コントローラーをシングルトンにすることです。プライベートコンストラクターがあるので、派生クラスのコンストラクターを気にせずにセッターインジェクションを安全に使用できます。代わりに、オーバーライド可能なinitialize()メソッドがあり(メソッドインジェクションが何らかの形で機能していると仮定)、基本的にコンストラクターの役割を果たします(派生コントローラーの初期化子のように)。このように、コンストラクターインジェクションはinitialize()メソッドのメソッドインジェクションに置き換えられます。この場合、派生コントローラーで管理することなく、すべてのシステム依存関係を利用できます。

しかし、グーグルですばやく検索すると、シングルトンコントローラーは悪い習慣だと満場一致で言われているようです。どうすればいいのかよくわかりません。私はおそらくこれを過剰に設計していますが、アプリケーションを将来にわたって利用でき、保守しやすいものにすることは別として、ベストプラクティスを適用するためのちょっとした演習だと考えているので、「適切に」実行したいと思います。
この場合のベストプラクティスは、必要なシステム依存関係を管理する責任を派生コントローラーに渡すことだと思います。依存関係は、派生コントローラーが実際にそれを必要とする場合にのみインスタンス化する必要があります。派生コントローラーがそれを使用することさえない可能性があるのに、なぜベースコントローラーにInputProviderを注入するのですか?しかし同時に、私は使いやすさに戻ってきます、$this->inputCodeIgniterのようなフレームワークなどで利用可能なメンバー。

私のディレマへのあらゆる貢献に感謝します。また、テキストの壁についてもお詫びしますが、今のところすべてが非常に抽象的であるため、説明を簡単にするコード例は考えられませんでした。

心から、
ひどく引き裂かれた個人

4

1 に答える 1

1

いくつかの解決策が可能です。

  • コントローラーの使用を禁止する__construct():それをprivate public finalにし、コントローラーに次のようなものをオーバーライドinit()させ、コンストラクターから呼び出します。次に、コンストラクターはすべての依存関係(リフレクション?他のもの?)を挿入し、すべての依存関係をで準備できるようにしinit()ます。

  • PHP-DI(免責事項:私はそれに取り組んでいます)のような既存のDIライブラリを使用できます。これにより、依存関係を定義できますが、コンストラクターで使用できます(魔法のようにそうです)。

そんな感じ:

<?php
use DI\Annotations\Inject;

class FooController {
    /**
     * @Inject
     * @var Bar
     */
    private $bar;

    public function __construct() {
        // The dependency is already injected
        $this->bar->sayHello();
    }

    public function setBar(Bar $bar) {
        return $this->bar = $bar;
    }
}

たとえば、これがZend Framework 1での作業方法です。コンストラクターを使用できないため、プロパティに挿入します。これがZF1統合プロジェクトです。

于 2013-02-01T11:28:46.213 に答える