オレオレ MVC を作ってみる(1)

CakePHP の構造が分かったので、簡易 MVC を作ってみます。
理由としては、

  • CakePHP を導入するまでもないかなぁ、という時?
  • 導入前に、そもそも MVC が、どういうものなのかを把握する時?
  • PHP で MVC の繋がりってどう作るんでしょうね?

といったところです。

いずれ、CakePHP に移行するという前提にして、命名規約などは CakePHP に準じます。

いわゆる

まずは view です。

<!-- views/magazine/index.php -->
<h1>雑誌一覧 magazine の表示</h1>
<table>
	<tr>
		<th>Magazine.id</th>
		<th>Magazine.name</th>
		<th>Publisher.name</th>
		<th>State.name</th>
	</tr>
	<?php foreach($Magazines as $item) : ?>
	<tr>
		<td><?php echo $item['Magazine']['id']; ?></td>
		<td><?php echo $item['Magazine']['name']; ?></td>
		<td><?php echo $item['Publisher']['name']; ?></td>
		<td><?php echo $item['State']['name']; ?></td>
	</tr>		
	<?php endforeach; ?>
</table>

CakePHP と同じように、$Magazines でモデルを参照できるようにします。

お次は、コントローラー

<?php
include 'models/magazine.php';
class MagazineController {
	var $name = 'MagazineController';
	function index() {
		// view に渡す変数
		global $Magazines;
		// モデルを作成して
		$magazine = new Magazine();
		// 検索
		$Magazines = $magazine->findAll();
		include('views/magazine/index.php');
	}
}
?>

モデルクラスを include して、index メソッド内では最後にビューを include して表示、って感じです。

で、肝心のモデルはどうなっているかというと、

<?php
class Magazine {
	var $name = 'Magazine';
	var $cn ;
	function open() {
		$this->cn = new PDO("mysql:host=127.0.0.1;dbname=moonmile_cake",
			"moonmile_cake","cakephp");
	}
	function close() {
		$this->cn = null;
	}

	function findAll() {
		$this->open();
		$sql = <<< HERE
select
	Magazine.id 	`Magazine.id`,
	Magazine.name 	`Magazine.name`,
	Publisher.id	`Publisher.id`,
	Publisher.name	`Publisher.name`,
	State.id		`State.id`,
	State.name		`State.name`
from 
	magazines as Magazine
	inner join publishers as Publisher
		on ( Magazine.publisher_id = Publisher.id ) 
	inner join states as State
		on ( Publisher.state_id = State.id )
	order by Magazine.id;
HERE;
		$stmt = $this->cn->query($sql);
		foreach($stmt as $item) {
			$row['id'] = $item['Magazine.id'];
			$row['name'] = $item['Magazine.name'];
			$table['Magazine'] = $row;
			$row['id'] = $item['Publisher.id'];
			$row['name'] = $item['Publisher.name'];
			$table['Publisher'] = $row;
			$row['id'] = $item['State.id'];
			$row['name'] = $item['State.name'];
			$table['State'] = $row;
			$items[] = $table; 
		}
		$this->close();
		return $items;
	}
}
?>

データベースからクエリで読み込んで、コントローラーから findAll メソッドの呼び出しでデータを設定しています。
クエリ文は慣れるとすらすら書けるでしょうし、データへの再設定もそれなりに…なのかなぁ。

さて、これらを動かすために、http://servername/magazine で表示させたい訳ですが、mod_rewirte を有効にして URL の書き換えを利用するために、次のように index.php を細工します。

<?php
$url = $_GET['url'];

$url = strtolower($url);
$pos = strpos($url,"/");
if ( $pos === false ) {
	$base = $url;
	$method = "index";
} else {
	$base = substr($url,0,$pos);
	$method = substr($url,$pos+1);
}

$classfile = $base."_controller.php";
$classname = strtoupper(substr($base,0,1)).substr($base,1).'Controller';

echo "classfile: $classfile<br/>";
echo "classname: $classname<br/>";
echo "method: $method<br/>";

include('controllers/'.$classfile);
$c = new ReflectionClass($classname);
$obj = $c->newInstance();
$method = $c->getMethod($method);
$method->invoke($obj);
?>

指定されたコントローラーのメソッドを呼び出すためにリフレクションを使います。多分、匿名関数の実行なんかを使う方がすっきり書けるのかもしれませんが、ひとまず。
ただし、この場合だと、http://servername/magazine/item/2 のように、雑誌の id が 2 の情報を得る、というような引数を指定することができないので、もう少し手を加える必要がありますね。


追記 2011/01/30
URL 書き換えの index.php ですが、../ 等を使って親ディレクトリのファイルを取れる可能性もあるので、実際に使うときはもう少し調節が必要です。このあたりは、パラメータを取得できるときにもで書き換えてみます(できるのか?)。

カテゴリー: 開発, CakePHP パーマリンク