ウィキペディアの記事(つまり、MVCを習い始めたばかりのほとんどの人はそこにたどり着く可能性が高いようです)には、不正確さと曖昧な言葉遣いがたくさんあります。一般的に、およびPHPで開発する場合-特に。
ここで見つけたMVCパターンの最も正しい定義:
MVC設計パターンでは、アプリケーションデータ、ユーザーインターフェイス、および制御ロジックを3つの個別のコンポーネント(モデル、ビュー、コントローラー)に分割し、各コンポーネントを個別に変更できるようにします。
この場合の「コンポーネント」という用語は、いくつかの一般的なCMSまたはフレームワークのコンポーネントとは関係がなく、たとえば、Bitrixコンポーネントは一般に3つすべてのMVCコンポーネントから構築されることを明確にしましょう。
上記の定義では、コンポーネントはコードの特定の個別の部分として理解される必要があり、それぞれがコントローラー、モデル、またはビューの役割の1つを果たし、モデルを使用してアプリケーションデータを抽出および操作します。ビューは、このデータをユーザーに表示する責任があります(つまり、 Webに対して、サーバー/ユーザーのHTML / CSSがサーバーによって生成されます)、コントローラーがオーケストラ全体を制御します。
古典的なWebアプリケーションスキーマを見てみましょう。
図1
![](https://habrastorage.org/storage2/7c7/85c/358/7c785c358bc7b5406252cd445fcf5389.png)
この図と次の図で、破線は制御情報(たとえば、ストア内の要求されたブログエントリや製品のIDなど)、および固体-アプリケーションデータ自体(データベース、ディスク上のファイルの形式、または場合によっては、RAM内-この質問はMVCパターンの範囲外です)。 Webに適用すると、要求と応答はHTTPを介して送信されるため、この図ではダッシュはHTTP要求と応答のヘッダーを示し、実線はその本文を示していると条件付きで想定できます。
要求1を受信すると、コントローラーはそれを分析し、処理の結果に応じて、次の回答オプションを提供できます(答えが4番である理由は、次の図から明らかになります)。
1.すぐにエラー応答を返します(たとえば、存在しないページを要求する場合は、HTTPヘッダー「404 Not found」のみを返します)
2.受信したリクエスト1が正しいと見なされる場合、データの表示または変更のリクエストであるかどうかに応じて、コントローラーは保存や読み込みなどの適切なモデルメソッドを呼び出します (図2のリクエスト2)。
図2
![](https://habrastorage.org/storage2/7ca/4a0/8f4/7ca4a08f4a455db95c824b196ae3d0b7.png)
重要な注意:MVCの概念は、特定のプログラミング言語に関連付けられているだけでなく、使用されているプログラミングパラダイムにも関連付けられていません。 つまり、OOPを使用せずにMVCを使用してアプリケーションを簡単に設計し、次の方法でオンラインストアの製品モデルを設計できます。
<? mixed Product_Load (int $id) { ... } // FALSE bool Product_Save (array $data) { ... } // TRUE $data, FALSE ?>
そのため、モデルから受け取った応答2に応じて、コントローラーは、最初の要求1に対する最終応答を形成するために呼び出すビューを決定します。
3.1。 失敗した場合-エラーメッセージの表示
3.2。 成功した場合-要求されたデータまたはストレージの成功に関するメッセージを表示するための送信(要求1がデータを変更する場合)。
図3
![](https://habrastorage.org/storage2/918/f00/e1a/918f00e1af97efd5886c84bcc8c46be6.png)
入力データの有効性とアクセス権(コントローラーまたはモデル)を誰がチェックするかという問題は、MVCパターンではそのような詳細が説明されていないため、非常に多くの論争の的となっています。 これは、この問題において、選択はあなた次第であることを意味します(または、お気に入りのフレームワークまたはCMSの作成者が作成しました)。
私たちの実践では、このアプローチを順守しています。
コントローラーは、入力データの「一般」(つまり、特定の要求とは無関係)の正確性、保存されたデータの有効性に関するモデルの要件への準拠、対応するモデルメソッド、およびアクセス権(個別のユーザークラスのアクセスメソッド)をチェックします 。
ViewをPHPで呼び出すために、Viewなどの特別なクラス(または複数のクラス)が設計される場合があります (これはフレームワークの実装のMVC記述でよく見られます)が、これはMVCの要件ではありません。
また、プレゼンテーションファイルはしばしばテンプレートと呼ばれ、いわゆるテンプレートエンジンを使用する場合、テンプレートエンジンはプレゼンテーションの役割を果たし、テンプレート(つまり、HTMLマークアップを直接含むファイル)はいくつかのフレームワークでレイアウトと呼ばれます 。
前の段落は非常に明確ではありませんか? 各ビューは個別のPHPファイルであり、PHP自体はincludeステートメントを使用して、回答3と回答4がリクエスト3を実行するように設計されているため、忘れてください(これはリクエスト1に対する回答ですか? )は、PHP自体によってブラウザに自動的に与えられます。
例を見てみましょう。
2つのプレゼンテーションオプション(テンプレート)があります。
<!-HTML.header->は、生成されたWebドキュメントのメインコンテンツに先行するHTMLコード(つまり、doctypeタグ、ヘッドコンテナ、ページヘッダーコードなどを含む)、および<! -HTML.footer-> -ほぼ同じ、ページのフッターのみ。
リスト1. product.tpl.phpテンプレートには、製品に関する情報が表示されます(呼び出しの時点で既に$ productオブジェクトが含まれています)。
<!-- HTML.header --> <h1><?=$product->Title;?></h1> <p>:<b class="price"><?=$product->Price;?></b></p> <p class="description"><?=$product->Description;?></p> <!-- HTML.footer -->
リスト2. error.tpl.phpテンプレートは、エラーメッセージ( $エラー変数に含まれています)を表示します。
<!-- HTML.header --> <h1 class="error">: <?=$error;?></h1> <!-- HTML.footer -->
リスト3.製品の表示に使用されるproduct.phpコントローラーは次のようになります。
<? include 'product.class.php'; // // , , // function Error ($error) { // , : header(' , , 400 404'); $error = ' , , '; include 'error.tpl.php'; // exit; } if (!$id = ...) // "" 1 error(...); // if (!$user->Access(...)) error(403); if (!$product = Product::Load($id)) // 2 2 error(' '); include 'product.tpl.php'; // 3 3 4 ?>
美しく最適化されたコードが好きな人は 、 HTML.headerブロックとHTML.footerブロックが両方のテンプレート(Views)のerror.tpl.phpとproduct.tpl.phpに複製されていることに気付くかもしれません。 save.php :
<!-- HTML.header --> <? // 3 ?> <!-- HTML.footer -->
... したがって、 基本的なMVCルールに違反します-コントローラー、モデル、ビューを分離します。
ただし、コードの重複は明らかな悪です。 どうする?
MVCからHMVCに移行する必要があります!
しかし、これは別の記事のトピックです。