web-dev-qa-db-ja.com

MVCで$ _POSTデータを処理する正しい方法は何ですか?

PHP=システム:ControllerViewからのリクエストを受け取り、$_POSTデータを含んでいます。これで、3つのデータを処理する方法:

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

現在、私はオプションAに従っていますが、それは間違っていると思うので、オプションCの使用を考えています。

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

[〜#〜] edit [〜#〜]現時点では、MVCフレームワークを使用していません。

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

36
Renato Dinhani

最良のオプションは、#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() methodをRequest::getPost()-のようなものに置き換えることもできますが、正しく構造化されたアプリケーションでは、the GETand POSTparameters同じ名前を共有しないでください。

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

servicesの作成を担当します。これには、ドメインビジネスロジックを domain objects に残したまま、アプリケーションロジックが含まれます)は、ドメインエンティティとストレージ抽象化の間の相互作用をプレゼンテーション層から分離するのに役立ちます。

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

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

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

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

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

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

おわりに:

理解しておく必要があることの1つは、WebベースのMVCアプリケーションのコンテキストでは、アプリケーションのUserがブラウザーであることです。あなたじゃないブラウザはリクエストを送信します。リクエストはルーティングメカニズムによって処理され、コントローラによって配布されます。そして、viewはブラウザに/と応答します。

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


更新

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

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

これを行うには、2つの条件があります。

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

このようにして、1つのアプリケーションですべての要件を満たすことができます。バリアントごとに異なるのは、bootstrapステージのみです。このステージでは、Requestインスタンスを作成し、適切なビューを選択します。

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

26
tereško

かつては、3層のアプリケーションアーキテクチャがありました。

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

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

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

ただし、ある時点で、クエリの内容を分析してサニタイズおよび検証する必要があります。これは、ビューがリクエストをフォーマットする方法によって異なります。サニタイズはコントローラータスクである場合があります(このリクエストにはこれらの値のみが含まれている必要があります)一方で、検証は間違いなくモデルタスクです(値はこれらのタイプである必要があります)。

興味深い質問は、いくつかのドメインオブジェクトに影響を与えるアクションにどのように対処するかです。そのためのロジックをどこに置きますか?

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

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

  • リクエストは最初にオブジェクトに変換されます
  • そのオブジェクトはルーティングオブジェクトを使用してルーティングされます
  • コントローラで処理されます
  • コントローラは、応答オブジェクトを構築するアクションによって関係するサービスに要求を渡します

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

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

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

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

他の答えについては this other question を参照してください。

tereško のおかげで、この件に関する貴重な情報を提供してくれました。

3
didierc

私はZendを使用しています。

2番目のオプション。

登録フォームの例

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

step -2 iサーバー側の検証を通じて、フォームの値(メールとURL、空の投稿の値など)を検証します。

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

手順4-コントローラがモデルを呼び出します。

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

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

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

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

 it helps in keeping code readable managebale .
1
Rinzler

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

例:WebインターフェースとWebサービスで同じモデルを使用できます。 Webでは$ _POSTは有効ですが、Webサービスでは無効です。そのため、モデルはデータの受信方法を気にせず、データを保存およびロードする方法のみを考慮します。

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

0
Shiv

いくつかの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