1.6.2で最新版のようなO/Rマッパーっぽい物を実装する
やっぱりORマッピングされるとすごく助かる!というのがあるので、それっぽい物を実装してみます。
今回は、Zend Frameworkにもある、ブログのようなブログじゃ無いチュートリアルを読み進めたところにある、「Create a Model and Database Table」を参考にしてみます。
準備
適当にいつも通りのサイトを作る感覚で、apps以下にmodelsフォルダを配置。
modelsフォルダ内に、「DbTable」を作成します。
Controller等は通常通りHogeController.php等で作ります。
modelの作成
モデルを作成していきますが、まずORマッパーってなによ!ってのですが、wikiを参考に。
要は、相互互換を取るための仲介役(であってるかな?)って事です。
それでは、modelの作成へ。
今回は以下のようなテーブルがあったとします。
create table `post` (id int(20) auto_increment,
title varchar(255) not null,
content varchar(255) not null
);
このテーブルをマッピングします。
まずは、Zend Frameworkの規則に則って、Post.phpというファイル名で、modelファイルを作成します。
Post.php内は以下の通りです。
require_once(APPLICATION_PATH. "models/PostMapper.php");class Post {
protected $_mapper ;
protected $_id ;
protected $_title ;
protected $_content ;
public function __set($name, $value) {
$method = "set". ucfirst($name) ;
if($name == "mapper" || !method_exists($this, $method)) {
throw new Exception("Call to undefined method, '{$method}'") ;
$this->$method($value) ;
}
}
public function _get($name) {
$method = "set". ucfirst($name) ;
if($name == "mapper" || !method_exists($this, $method)) {
throw new Exception("Call to undefined method, '{$method}'") ;
$this->$method() ;
}
}
public function getMapper() {
if(!$this->_mapper) {
$this->setMapper(new PostMapper()) ;
}
return $this->_mapper ;
}
public functio setMapper($mapper) {
$this->_mapper = $mapper ;
}
public function getId() {
return $this->_id ;
}
public function setId($id) {
$this->_id = $tid ;
return $this ;
}
public function getTitle() {
return $this->_title ;
}
public function setTitle($title) {
$this->_title = $title ;
return $this ;
}
public function getContent(){
return $this->_content ;
}
public function setContent($content) {
$this->;_content = $content ;
return $this ;
}
}
なっげ・・・・
と、一応このような(誤字・脱字あったら教えて下さい・・・)形になります。
次に
マッパークラスを作成します。
これは、models直下に「PostMapper.php」としてファイルを作成します。
これは以下のようになります。
require_once(APPLICATION_PATH. "models/DbTable/Post.php") ;require_once("Zend/Db.php");
class PostMapper {
protected $_dbTable ;
public function getDbTable() {
if(!$this->_dbTable) {
$this->setDbTable("DbTable_Post") ;
}
return $this->dbTable ;
}
public function setDbTable($dbTable) {
if(is_string($dbTable)) {
$db = Zend_Db::factory(Zend_Registry::get("database")) ;
$dbTable = new $dbTable(array("db" => $db)) ;
}
if(!Zend_Db_Table_Abstract instanceof $dbTable) {
throw new Exception(";Invalid DbTable") ;
}
$this->_dbTable = $dbTable ;
}
public functoin find($id, Post $post) {
$data = $this->getDbTable()->find($id)->getRow(0) ;
$post->setId($data->id)
->setTitle($data->title)
->setContent($data->content);
}
}
こんな感じです。
このPostMapper.phpは、これから作成するDbTable/Post.phpとPost.phpをつなぎ合わせる(橋渡し?)している部分です。
ですので、基本的に、このクラスはZend_Db_Table_Abstract.phpで定義されている「find」、「fetchAll」等のようなメソッドを再定義し、マッピングを行うだけにしておきます。
次に
先ほど作成したDbTableフォルダ以下にPost.phpというファイル名でファイルを作成します。
ファイル内容は以下のようになります。
require_once("Zend/Db/Table/Abstract.php") ;class DbTable_Post extends Zend_Db_Table_Abstract {
protected $_name = "post" ;
protected $_primary = "id" ;
public function init() {
$adapter = $this->getAdapter() ;
// ここは最新版では恐らくexecになると思います。
// 直接set names 送るのはいろいろ良くないと思うのですが、あえてココでは省略します。
// ゴメンナサイ
$adapter->query("SET NAMES utf8") ;
}
}
このファイルはデータベースを操作する上で、いろいろ定義(テーブル名など)するだけで、データベースの操作を簡単に行えるようになるファイルです。
簡単に言うと、データベースの定義 == DbTable/Post.phpになります。(実際には違いますのでお気をつけ下さい)
ひとまず以上でORマッパーっぽい物の定義が終わりました。
どうなってんの?
これら3つのファイルは依存しあっています。
流れは、
「models/Post.php」から「PostMapper.php」が呼び出され、呼び出された「PostMapper.php」は「models/DbTable/Post.php」を呼び出し、記事を見つけたり、更新処理等を行っています。
作る際の手間は相当かかりますが、長スパンで見たときには必ず効率は上がります。(※ただしイケメ(ry))
自分も
ORマッパーはよく理解していません。
wikiを読んでみましたが(ざっくばらんに)大体の意味でしか理解していません。
なので、間違いはきっとどこかにあるはずだと思います。
ですので、ご指摘などは、遠慮無くコメントに記述していただければと思います。
追記
09/10/06
Zend_Loader::registerAutoloader()を使うとrequire_onceの数が減るとおもいます。
さらに言うと、作成していったModelやDbTableクラスはパスさえ通してしまえば、Zend_Loader::registerAutoload()を実行下だけでファイルを自動読み込みしてくれます。