- 更新日: 2017年04月04日
- 公開日: 2015年12月08日
ゼロから始めるPHP講座 Vol.44 MVCモデル③~MVCの使用例
ゼロから始めるPHP講座 MVCモデル③~MVCの使用例
MVCモデルの使用例
より具体的な利点を学ぶため、MVCモデルを活用した例を作成してみましょう。
各ファイル作成の上、適切なディレクトリにファイルを置いてください。 ファイル: goods_insert.php, goods_insert.php, goods_insert_result.php
<!--?php
// 設定ファイル読み込み
require_once '../include/conf/const.php';
// 関数ファイル読み込み
require_once '../include/model/function.php';
// 変数初期化
$goods_name = ''; // 商品名
$price = ''; // 価格
$err_msg = array(); // エラーメッセージ用配列
// リクエストメソッド取得
$request_method = get_request_method();
if ($request_method === 'POST') {
// POST値取得
$goods_name = get_post_data('goods_name');
$price = get_post_data('price');
//////////////////////////////////////////////
// 本来はここで商品名や価格の入力値チェックを行います。
// MVCモデル理解優先のため省略しています。
//////////////////////////////////////////////
// DB接続
$link = get_db_connect();
// 新規商品追加
if (insert_goods_table($link, $goods_name, $price) !== TRUE) {
$err_msg[] = 'INSERT失敗';
}
// DB切断
close_db_connect($link);
// 特殊文字を変換
$goods_name = entity_str($goods_name);
$price = entity_str($price);
if (count($err_msg) === 0) {
// 新規追加完了テンプレートファイル読み込み
include_once '../include/view/goods_insert_result.php';
exit;
}
}
// 新規追加テンプレートファイル読み込み
include_once '../include/view/goods_insert.php';
<!DOCTYPE html-->
<meta charset="UTF-8">
<title>商品追加</title>
<!--?php if (count($err_msg)) { ?-->
<!--?php foreach ($err_msg as $value) {?-->
<!--?php print $value; ?-->
<!--?php } ?-->
<!--?php } ?-->
<form action="goods_insert.php" method="POST"> 商品名:
<input type="text" name="goods_name" value="<?php print $goods_name; ?>">
価格:
<input type="text" name="price" value="<?php print $price; ?>">
<input type="submit" value="追加"></form>
<meta charset="UTF-8">
<title>商品追加完了</title>
商品名:
<!--?php print $goods_name; ?--> 価格:
<!--?php print $price; ?-->を新規登録しました[商品一覧へ](goods_list.php)
また以下ファイルをコピーして作成してください。 ※成果物として残しておく必要がない人は、ファイル名変更でも構いません。
- /htdocs/controller.php → /htdocs/goods_list.php
- /include/model/model.php → /include/model/function.php
- /include/view/view.php → /include/view/goods_list.php
model.phpをコピーしたfunction.phpに対して、以下の関数を追記してください。
/**
\* insertを実行する
\*
\* @param obj $link DBハンドル
\* @param str SQL文
\* @return bool
\*/
function insert_db($link, $sql) {
// クエリを実行する
if (mysqli_query($link, $sql) === TRUE) {
return TRUE;
} else {
return FALSE;
}
}
/**
\* 新規商品を追加する
\*
\* @param obj $link DBハンドル
\* @param str $goods_name 商品名
\* @param int $price 価格
\* @return bool
\*/
function insert_goods_table($link, $goods_name, $price) {
// SQL生成
$sql = 'INSERT INTO goods_table(goods_name, price) VALUES(\'' . $goods_name . '\', ' . $price . ')';
// クエリ実行
return insert_db($link, $sql);
}
/**
\* リクエストメソッドを取得
\* @return str GET/POST/PUTなど
\*/
function get_request_method() {
return $_SERVER['REQUEST_METHOD'];
}
/**
\* POSTデータを取得
\* @param str $key 配列キー
\* @return str POST値
\*/
function get_post_data($key) {
$str = '';
if (isset($_POST[$key]) === TRUE) {
$str = $_POST[$key];
}
return $str;
}
goods_insert.php(Controller)へアクセスすると、商品追加を行うページが表示されます。
プログラムで行っている処理自体はこれまでと変わりありませんが、全部でファイルを7つ利用しています。ファイル構成を図で表すと以下のようになります。
Model・View・Controllerのファイル数が1:1:1ではないことが分かります。
function.php(Model)は、goods_insert.php(Controller)とgoods_list.php(Controller)で共通利用しています。以前ユーザー定義関数の利点にて、以下3つを挙げました。
- プログラムが読みやすくなる
- コード(関数)の使い回しができる
- 変更箇所が少なくなる コード(関数)の使い回しは、 別ファイルに関数をまとめておきファイル読み込みを行うことで、定義した関数を複数のControllerファイルで利用することができます。
今回の場合、get_db_connect関数とclose_db_connect関数を共通で利用しています。
// DB接続
$link = get_db_connect();
// 新規商品追加
if (insert_goods_table($link, $goods_name, $price) !== TRUE) {
$err_msg[] = 'INSERT失敗';
}
// DB切断
close_db_connect($link);
// DB接続
$link = get_db_connect();
// 商品の一覧を取得
$goods_data = get_goods_table_list($link);
// DB切断
close_db_connect($link);
変更箇所が少なくなるのも同様で、function.phpにまとめた関数を共通で利用していれば、関数の処理を1箇所変えるだけで、その関数を利用している処理全てが変更となります。
また1行しかないユーザー定義関数も複数ファイルから利用していると、何か変更があった際に変更箇所が1箇所で済みます。
/**
\* DBとのコネクション切断
\* @param obj $link DBハンドル
\*/
function close_db_connect($link) {
// 接続を閉じる
mysqli_close($link);
}
例えばデータベース切断はmysqli_close関数を実行しているだけですが、PHPであらかじめ用意されているmysqli_close関数も仕様が変更になることはあります。
この場合、処理をModelにまとめておくで、変更箇所が1箇所で済みます。
実際、PHPには以前使われていたが現在は非推奨(将来削除予定)となっているmysql_close()という関数があります。 参照: mysql_close()
このようにModelとして処理を独立されることで、大きなメリットが生じます。
Controllerの役割はViewとModelの制御ですが、goods_insert.php(Controller)ではModelへ処理を依頼し、返答によって読み込むViewを使い分けています。
// 特殊文字を変換
$goods_name = entity_str($goods_name);
$price = entity_str($price);
if (count($err_msg) === 0) {
// 新規追加完了テンプレートファイル読み込み
include_once '../include/view/goods_insert_result.php';
exit;
}
}
// 新規追加テンプレートファイル読み込み
include_once '../include/view/goods_insert.php';
「商品名」「価格」の入力があった場合、商品追加処理をModelに依頼しています。
Modelへ依頼した商品追加処理の返答で処理が成功していた場合は../include/view/goods_insert_result.phpを読み込んでいます。
../include/view/goods_insert_result.phpを読み込んだ場合、次の行でexitをしています。exitはプログラムの実行を終了し、以降の処理を行いません。
それ以外の場合は../include/view/goods_insert.phpを読み込んでいます。 ※URLはどちらも同じgoods_insert.php(Controller)となる
Controllerはこのように処理結果に応じてViewを使い分けることもできます。
今まで処理が成功した場合と失敗した場合のどちらも同じファイルにHTML/CSSを記載していましたが、ファイルを分けることで、コードが読みやすくなります。
また紹介はしませんが、Viewを使い回すことも可能です。
補足
MVCモデルについて、「Model」「View」「Controller」それぞれの関係は以下のようになると本章で説明してきました。
しかしこれは「MVC2」と呼ばれるモデルで、MVCを参考にWebサービス用に拡張したもので、本来のMVCモデルとは異なります。
混合しないよう「別なモデル」とだけ覚えておいてください。
課題
ひとこと掲示板をMVCモデルに沿った内容に改修してください。
ControllerとViewはファイルを新規作成し、Modelについてはfunction.phpへ追記をしてください。 ファイル名: bbc_mvc.php
利用者が名前とコメントを入力し、発言できる。 利用者の過去発言内容をデータベースで管理する。 全ての利用者の過去発言を一覧で見ることができ、「名前、コメント、発言日時」の最低限3つを1行ずつ表示する。 利用者の名前は最大20文字以内とし、それ以上の場合はエラーメッセージを表示し、発言できないようにする。 利用者のコメントは最大100文字以内とし、それ以上の場合はエラーメッセージを表示し、発言できないようにする。 利用者の名前、コメントのどちらか又は両方が未入力だった場合、エラーメッセージを表示し、発言できないようにする。 要件については、以前から変更はありません。
NEXT LESSON ☛ Cookieとは
PREV LESSON ☛ MVCモデル②~MVCの利点
- この記事を書いた人
- CodeCampus編集部