Nullyのぶろぐ

仙台から東京へ転勤したエンジニアのブログ

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()を実行下だけでファイルを自動読み込みしてくれます。