37

私のPHPシステムでは、一般的なMVCの状況があります:含まControllerれているデータからリクエストを受け取ります。これで、データを処理する方法が 3 つあります。View$_POST

a) はControllerのみを呼び出し、はデータModelModel処理し$_POSTます。
b)はデータを変数にController変換し、$_POSTに渡しますModel
c) はデータをのドメイン オブジェクトにController変換し、そのオブジェクトを に渡すだけです。$_POSTModelModel

現在、選択肢Aに従っていますが、それは間違っていると思うので、選択肢Cを使用することを考えています.

では、MVC によると、$_POSTデータを処理する正しい方法は何でしょうか?

EDIT現時点では、MVC フレームワークは使用していません。

EDIT 2一般に、Controllerブラウザ、Webサービス、オフラインアプリケーションなどからのリクエストを同じように処理するか、それぞれに独自のものがありControllerますか?

4

5 に答える 5

26

最良のオプションは、いくつかの変更を加えた#2のアプローチを使用することです。
私はそれを次のように書きます:

public function postLogin( $request )
{
     $service = $this->serviceFactory->build('Recognition');
     $service->authenticate( $request->getParam('username'),
                             $request->getParam('password') );
}
// Yes, that's the whole method

Requestインスタンスのようなものを使用してユーザーの入力を抽象化した場合は、実際に変数を作成する必要はありません。

また、Request::getParam()メソッドを次のようなものに置き換えることもできますが、正しく構造化されたアプリケーションでは、パラメータとパラメータが同じ名前を共有すべきではないRequest::getPost()という結論に達しました。GETPOST

コード スニペットに表示されるのserviceFactoryは、コントローラーとビュー インスタンスの両方に挿入するオブジェクトです。コントローラーとビューの間で同じサービス インスタンスを共有できます。

サービス の作成を担当します(アプリケーション ロジックを含み、ドメイン ビジネス ロジックはドメイン オブジェクトに残します)。これにより、ドメイン エンティティとストレージ抽象化の間の相互作用をプレゼンテーション レイヤーから分離することができます。

その他のオプションについて:

  • コントローラーはモデルのみを呼び出し、モデルは $_POST データを処理します。

    MVC および MVC にインスパイアされたデザイン パターンでは、モデルはユーザー インターフェイスもプレゼンテーション レイヤーも全体として認識する必要はありません。PHPの$_POST変数はスーパーグローバルです。

    モデル レイヤーで使用すると、コードは Web インターフェースや特定のリクエスト メソッドにさえバインドされます。

  • コントローラは $_POST データをモデルのオブジェクトに変換し、そのオブジェクトをモデルに渡すだけです

    あなたがこれで何を意味したのか完全にはわかりません。ユーザーのリクエストを含む抽象化のインスタンス化について話していたようです。ただし、この場合、コントローラーは、 SRPに違反する上記の構造のインスタンス化/作成を担当します。

結びのメモ:

理解しなければならないことの 1 つは、Web ベースの MVC アプリケーションのコンテキストでは、アプリケーションのユーザーはブラウザーであるということです。あなたじゃない。ブラウザはリクエストを送信します。リクエストはルーティング メカニズムによって処理され、コントローラによって配布されます。そして、ビューはブラウザへの応答を生成します。

もう 1 つは、モデルはクラスでもオブジェクトでもありません。モデルはレイヤーです。


アップデート

通常、ブラウザ、Web サービス、オフライン アプリケーションなどからのリクエストは同じコントローラで処理されますか、それともそれぞれに独自のコントローラがありますか?

すべての形式のアプリケーションを処理する単一のコントローラーを持つことができるはずです。ただし、これは条件付きであり、実際には 3 つのユースケースすべてで同じアプリケーションを使用しています。

そのためには、次の 2 つの条件があります。

  • Requestコントローラーが受け取るインスタンスを抽象化する必要があります
  • ビューはコントローラの外部でインスタンス化する必要があります

このようにして、1 つのアプリケーションですべての要件を満たすことができます。各バリアントが異なる唯一のものは、Requestインスタンスを作成して適切なビューを選択するブートストラップ段階です。

あなたが説明した状況では、RESTまたはSOAPサービスは通常のWebアプリケーションとは異なる応答を生成することが期待されるため、変更部分は実際にはビューになります。

于 2012-11-15T11:44:22.057 に答える
3

むかしむかしは、3 層アプリケーション アーキテクチャでした。

それはすべて MVC フレームワークに依存します。通常、Controller は、ドメイン オブジェクトを操作するユーザーとモデル層の間のリンクを行います。

PHP での MVC の初期の頃、モデル レイヤーは実際にはドメイン オブジェクトであり、その目的のためにモデルと呼ばれていました。データのOO表現のみを提供する、いわゆるシンモデルを好む人もいました(これにより、永続性が簡素化されます)。その場合、コントローラはいわゆるアクションを再グループ化し、HTTP リクエストに関連する処理の大部分を含めます (ファット コントローラ)。

他の人は、専用のメソッド (fat モデル) を使用して、前述の処理のほとんどをオブジェクト モデルに組み込みました。

ただし、ある時点で、クエリのコンテンツを分析してサニタイズおよび検証する必要があります。これは、ビューがリクエストをどのようにフォーマットするかによって異なります。サニタイズはコントローラー タスク (この要求にはこれらの値のみを含める必要があります) である可能性がありますが、検証は間違いなくモデル タスクです (値はこれらの型である必要があります)。

興味深い質問は、複数のドメイン オブジェクトに影響を与えるアクションにどのように対処するかということです。その論理をどこに置くか。

現在、モデル レイヤーは、レイヤー間の依存関係をそれぞれのインターフェイスのみに制限するために、ドメイン オブジェクトをコントローラーの邪悪な把握から分離するサービスで構成されています。これは、ほとんどの要求処理が行われる場所です。

たとえば、Symfony2は、この質問に対する賢明な答えを提供します。リクエストの処理の各ステップは、次のように記述できる専用のコード片で実装されます。

  • リクエストは最初にオブジェクトに変換されます
  • そのオブジェクトは、ルーティング オブジェクトを使用してルーティングされます
  • コントローラーに処理されます
  • コントローラーは、アクションに関連するサービスにリクエストを渡します。これにより、レスポンス オブジェクトが構築されます。

その後、サービス ジョブはいくつかのステップで分割されます。

  • 検証 (別のファイルに記述されたルールに依存する専用オブジェクトを使用)、
  • ドメイン オブジェクトの構築/更新 (必要に応じて db との間のシリアル化を使用)、
  • 応答のテンプレートの選択、
  • ドメインからの関連データを含むテンプレートの人口。

CakePHPは、同様の概念に従うもう 1 つの一般的なフレームワークです。単純なコントローラーと、ドメイン オブジェクトをカプセル化するサービスです。

一般的な概念についてのより良い洞察については、この質問を参照してください。

他の回答については、この他の質問を参照してください。

この件に関してかけがえのない情報を提供してくれたtereskoに感謝します。

于 2012-11-13T11:54:47.757 に答える
1

私はZendを使用しており、以下をフォローしています

2番目のオプション。

登録フォームの例

step- 1 フォームは、指定されたコントローラーに投稿値を送信します

ステップ-2サーバー側の検証を通じて、たとえばフォームの値(メールとURL、および空の投稿の値)を検証します。

ステップ-3チェックされた投稿データを変数または全体でモデルに送信します。

ステップ 4 - コントローラがモデルを呼び出します。

ステップ-5 モデルは投稿値を挿入し、新しいユーザーを作成します。

使用するフレームワークやアプローチに関係なく、2番目のオプションの方が優れていると思います。

注 - 同じコントローラーですべてを処理できるのは、アプリケーション ロジックによって異なります。

 but i prefer to keep different controller for differnt user request and user types

 it helps in keeping code readable managebale .
于 2012-11-22T13:54:38.070 に答える
0

「C」が最適なオプションです。モデルは主にストアおよびロード操作を処理する一般的なものであると想定されているため、生の$POSTデータをモデルに入れないでください。

例:同じモデルをWebインターフェイスとWebサービスで使用できます。Webでは$_POSTは有効ですが、Webサービスでは無効です。したがって、モデルはデータの受信方法を気にせず、データの保存と読み込みの方法だけを気にします。

Yiiは間違いなくMVCのクリーンな実装です。

于 2012-11-15T13:48:34.167 に答える
0

いくつかの MVC フレームワークを見てください。

たとえば、Yii では、action内にそのようなコードを書くことができます:

$model = new Model();
if(isset($_POST['Model'])) {
    $model->attributes = $_POST['Model'];
}

すべてattributesのモデルが検証ルールを通過する必要があることに注意してください。Yii では検証が適用されます (実際には、前に)$model->save()

見る:

  1. http://www.yiiframework.com/doc/guide/1.1/en/form.model#securing-attribute-assignments
  2. http://www.yiiframework.com/doc/guide/1.1/en/basics.mvc
于 2012-11-13T11:26:33.877 に答える