0

おはようございます。最近、mvc パターンに関する記事を読みました。そこにあるほとんどの php フレームワークは mvc パターンを間違って実装しているということです。 php master mvc pattern part 1 php master mvc pattern part 2 さて、これを読んでその実装を見てみると、疑問が生じました。モデルで呼び出されたメソッドをビューで呼び出すにはどうすればよいでしょうか。私が言おうとしているのはこれです。これは記事のコードの一部です。

<?php
$model = $_GET['model'];
$view = $_GET['view'];
$controller = $_GET['controller'];
$action = $_GET['action'];

if (!(empty($model) || empty($view) || empty($controller) || empty($action))) {
    $m = new $model();
    $c = new $controller($m, $action);
    $v = new $view($m);
    echo $v->output();
} 

この記事を読んだ後、この設計パターンの小さな実装を作成し、次のコードがあるとします。

<?php
class Index extends Controller
{
   public function __construct(IndexModel $model, $action)
   {
       $this->model = $model;
   }
   public function someAction($id)
   {
       $this->model->getData($id);
   }
}
class Index extends View
{
   public function __construct(IndexModel $model, $action)
   {
       $this->model = $model;
   }
   public function someAction()
   {
       $this->model->getData();
   }
}
class Index extends Model
{
   public function __construct()
   {
        //Some Code Here
   }
   public function someAction()
   {
       // Inserting Data into database.
   }
}

ご覧のとおり、コントローラーとビューの両方で同じメソッドを呼び出して、データベースからデータを取得しています。しかし、私が正しく知っていれば、ビューがコントローラーの仕事を処理する必要があるため、$id はビューまたはそのようなもので再度解析するのに適切ではありません。では、これはどのように解決できますか?

4

1 に答える 1

4
  1. コントローラーとモデルのパーツの間に 1:1 の相関関係はありません(注: 「モデル」ではなく、_モデル_ のパーツ)。「インデックス コントローラー」があるからといって、「インデックス モデル」と「インデックス ビュー」が必要というわけではありません。
  2. M、V、および C は一緒に構築されません。コントローラーが構築され、次に、どのモデル メソッドをロード/構築/呼び出すか、およびどのビューが要求に応答するかを決定します。
    1. コントローラーがビューを呼び出すかどうか、またはモデルがビューを「更新」する必要があるかどうかについての議論があります。Web リクエストは一時的なものであり、「一定の」ビューがないため、後者は PHP ではほとんど意味がありません。元の SmallTalk や Obj-C などの環境により適しています。
  3. 最初のコード スニペットはempty(こちらを参照) の使用方法がひどいため、すべてのパーツを一緒に構築するべきではありません。

MVC は次のようにアプローチする必要があります。

  • モデル アプリです。単なる「データ ハンドラー」や「データ ストア」ではなく、コア アプリです。ビジネス ロジックに関して、アプリが行うことはすべて「モデル」です。これには、電子メール通知の送信、データベースのメンテナンス作業、およびそのような補助的なものが含まれます。これらはすべてモデルに含まれています。
  • ビューは、さまざまな形式の出力を生成する役割を果たします。ビューは、モデルとやり取りして、その仕事を行うために必要なデータを取得できる必要があります。データはビューに「プッシュ」されるべきではなく、ビューは必要なデータを「プル」できる必要があります。それ以外の場合、ビューの外部にある何かが、ビューが必要とするデータを知る必要があります。つまり、ビュー ロジックはビューに含まれていません。
  • コントローラーは、着信要求に応答して正しいモデル メソッドとビューを呼び出すために残されている、ほんの少しの接着剤です。

私は通常、これらの部分を次のように構成します。

  • このモデルは、データ ストレージ ハンドラー、「プリミティブ」 (個々のビジネス オブジェクトをモデル化するクラス)、「サービス」など、さまざまな部分で構成されています。「サービス」には、アプリが実行できるすべての「アクション」が含まれており、モデル API を形成します。「ユーザーの登録」や「X から Y までの日付範囲のすべてのレコードの取得」など、アプリで何かを「実行」したい場合はいつでも、サービス API に専用のメソッドが1 つあります。このサービス API を見るだけで、アプリが「行う」すべてのことを列挙できるはずです。
  • 「ディスパッチャー」または「サービス ロケーター」、またはこれらのサービス クラスのインスタンス化を簡素化し、誰かがそれらを呼び出せるようにする依存性注入コンテナーのいずれかであるオブジェクトが 1 つあります。コントローラーはこれらのいずれかを取得し、ビューも取得します。
  • URL に基づいて「大まかなルーティング」を行い、コントローラー メソッドを呼び出すルーターがあります。コントローラーはさらにリクエストの詳細を確認し、モデル メソッドを呼び出すか、ビューで応答するかを決定します。
  • ビューは、リクエストの詳細に基づいて、一部のデータを表示する最良の方法を決定する場合があります。たとえば、HTML ページで応答するか、JSON データ blob で応答するかなどです。RESTful サービスにどうぞ。

大まかな擬似コード:

$r = new Router;
$r->route($_GET, $_POST, $_SERVER); // or something like that

これは次のようなものにディスパッチします:

class FooController {

    public function __construct(ServiceLocator $services) { ... }

    public function bar(Request $request) {
        $request->assertIsPost();
        $this->services->locate('Baz')->froogleTheWibbles($request->getPostParams());
        (new BarView($this->services))->displayWibbles($request);
    }

}

class BarView {

    public function __construct(ServiceLocator $services) { ... }

    public function displayWibbles(Request $request) {
        switch ($request->accepts()) {
            case 'html' :
                $this->loadTemplate(...);
                ...
            case 'json' :
                echo json_encode($this->services->locate('Baz')->getWibbles());
        }
    }

}

そして、モデルは必要なことは何でもします...

class Baz {

    public function froogleTheWibbles(array $data) {
        foreach ($data as $wibbleData) {
            $wibble = new Wibble($wibbleData);
            $this->wibbleStore->save($wibble);
        }
        ...
    }

}

MVC には「1 つの答え」はありません。重要な部分は、入力と出力に関係なく、アプリが「行う」すべてのものがモデルに含まれていることです。ビューは、要求に応じて可能な限り独立して適切な出力を生成できます。コントローラーはほんのわずかです。入力条件を処理する接着剤のビット。これを実現するにはさまざまな方法があります。重要な設計原則は、ビューとコントローラーがさまざまな条件 (Web ページ、JSON API、XML API、SOAP API、CLI 呼び出し、ZeroMQ ノードなど) に合わせて交換可能であるという認識であるべきですが、「モデル」はそうではありません。

于 2013-06-24T08:50:29.277 に答える