2

さて、私は自分の仕事をしているいくつかのコントローラーを持っていましたが、今はさらにいくつかのコントローラーを作成しました。新しいコントローラーのアクションの途中で、古いコントローラーで適切なコードを書いたことを思い出しました。

たとえば、oldController@handyAction の場合

some_good_codez();

そして newController@newAction で

$myOldController = Load::controller('oldController'); // I wish Laravel had this?
$myOldController->handyAction();
4

1 に答える 1

9

これは間違っています。コントローラーは、http リクエストを受信し、モデルからデータを取得し、それをビューに渡すという 1 つの責任のみを負う必要があります。コントローラーが別のコントローラーと「対話」する必要がある場合、それはおそらく、それらでデータを処理しているか、それらを介してデータを読み取っているためであり、データを処理することはコントローラーではなくモデルの責任であるため、そうすべきではありません。

まず、 SOLID単一責任の原則を見てみましょう。Taylor Otwell の本 Laravel: From Apprentice To Artisanを購入できる場合は、それを実行してください。Laravel で SOLID 原則を実装する方法についての良いアイデアが得られます。

次に、2 つの異なるコントローラーでメソッドを使用する必要がある場合は新しいクラスを作成し、このクラスを両方のコントローラーで使用します。次のようにコードをリファクタリングするだけです。

class MyController1 extends Controller {

    public function __construct(MyClass $class)   
    {
        $this->myClass = $class;
    }

    public function store()
    {
        $this->myClass->doWhatever();
    }

}

class MyController2 extends Controller {

    public function __construct(MyClass $class)   
    {
        $this->myClass = $class;
    }

    public function update()
    {
        $this->myClass->doWhatever();
    }

}

class MyClass {

    public function doWhatever()
    {
        return 'done';
    }

}

これはまだ間違っていますが、少し良くなりました。

さらに優れているのは、データ リポジトリでデータを処理することです。Repository Pattern をご覧ください。 この Taylor のビデオでは、その方法について良いアイデアが得られます。テスト容易性について述べていますが、それだけではありません。ドメイン リポジトリを作成し、その中に 2 つ以上のモデルを混在させ、それらのモデルからのデータを 1 つのクラスで処理できます。リポジトリ パターンを使用するコードは、次のようになります。

インターフェイス (コントラクト) を作成します。

interface MyDataRepository {

    public function getInfoA();
    public function getInfoB($dataA);

}

このインターフェースを実装するクラスを作成します

class MyData implements MyDataRepository {

    public function __construct(MyModelA $dataA, MyModelB $dataB)   
    {
        $this->dataA = $dataA;
        $this->dataB = $dataB;
    }

    public function getInfoA()
    {
        return $this->dataA->processData();
    }

    public function getInfoB($dataA)
    {
        return $this->dataB->processData( $this->getInfoA() );
    }

}

[編集]

リポジトリは、必要なものをすべて入れてそこから必要なものを抽出できるバッグと考えてください。

このリポジトリでは、Laravel の IoC コンテナによってインスタンス化された 2 つのモデル (MyModelA e MyModelB) を使用しています。メソッドでgetInfoBは、リポジトリは両方を使用してデータを生成し、コントローラに返します。

これはすべてドメイン駆動開発によるものです。ドメインは、注文、ユーザー、アイテム、配送、および支払いテーブルからのデータを使用して構築される、注文のような複雑なモデルです。このすべての情報がないと、支払いページに表示する注文が実際にはありません。そのため、注文リポジトリを作成し、すべての ORM を 1 つのクラスに混在させます。このクラスには、これらのテーブルからデータを取得して送り返す単一の責任があります。あなたのコントローラー。

[/編集]

インターフェイスのインスタンスが必要な場合は、Laravel にそのクラスをインスタンス化するように指示する必要があります。

App::bind('MyDataRepository', 'MyData ');

これは、インターフェイスを使用している場合にのみ行われます。ここでは具象クラスを使用して同じことを行っており、何も通知する必要はありません。Laravel は何をすべきかを知っています。

public function __construct(MyClass $class)   
{
    $this->myClass = $class;
}

そして、リポジトリを使用してコントローラーを作成します。

    class MyController1 extends Controller {

    public function __construct(MyDataRepository $data)   
    {
        $this->data = $data;
    }

    public function store()
    {
        $this->data->getInfoA();
    }

}

class MyController2 extends Controller {

    public function __construct(MyDataRepository $class)   
    {
        $this->data = $data;
    }

    public function update()
    {
        $this->myClass->getInfoB();
    }

}

Laravel はクラスのインスタンスを自動的にインスタンス化します。それを機能させるために他に何もする必要はありません。

于 2013-10-21T14:01:35.960 に答える