FuelPHPでMongoDBを使う

FuelPHP Advent Calendar 2011、9日目です。
前日は@ounziw さんの「FuelPHP の view に PHPTAL デザインテンプレートを使う」でした。


FuelPHPはMongoDBも扱えるということで触ってみました。FuelPHP1.1-RC1を使ってます。

まずはMongoDBとPHPドライバ pecl mongoをインストールした状態から始めます。
pecl mongoは下記コマンドで一発インストール可能です。

pecl install mongo

ちょっと古いバージョンのpecl mongoだとセグメンテーションエラーが出たりするので、古いのが入っている人は最新版にするのをおすすめします。私が作ったPeclMongoの新バージョンがあればツイートするボットをフォローしてもらえると、すぐにアップデートタイミングがわかります :)
https://twitter.com/pecl_mongo_bot


MongoDBは最初にDBやテーブルを作らなくても、insert操作が発生した時に自動的に生成します。
Fuelから扱う場合も、特に最初にテーブルは作らなくても問題ありません。

では、最初にどのデータベースを扱うかの定義から。ここではblogというDBを利用する宣言をします。
app/config/db.php

return array(
  'active' => 'default',
    'mongo' => array(
    	'default' => array(
        	'hostname'  => '127.0.0.1',
            'port'      => 27017,
            'database' => 'blog',
        )
	),
);


FuelでのMongoDB操作は、Mongo_Dbインスタンスを生成してメソッドを呼ぶだけなのでお手軽です。
Mongo_DbのAPIドキュメントはここにあります。
http://docs.fuelphp.com/classes/mongo/methods.html

下記では、postsテーブルからデータをfindして取得しています。

$mongodb = \Mongo_Db::instance();
$results = $mongodb->get('posts');

ORMとの連携は特にないので、RDBで使ってる\ORM\Modelのメソッドなどは利用できません。
これ使えばいけるかもしれません(未検証)
https://github.com/philsturgeon/fuel-mongo-odm


データ保存は

$mongodb = \Mongo_Db::instance();
$results = $mongodb->insert('posts', 
	array('name' => 'ichi', 'body' => 'test'));

のように、配列でデータを入れます。

MongoDBはカラムの中にさらに配列を入れることも可能です。

$mongodb = \Mongo_Db::instance();
$results = $mongodb->insert('posts', 
	array('name' => 'ichi', 'body' => array('aa','bb')));


とりあえず作ったサンプルアプリのコードをはっておきます。

まずはモデル
app/classes/model/blog.php

<?php
use \Model_Crud;
class Model_Blog extends Model_Crud
{

protected static $_table_name = 'posts';

public static function findMongo() {
	$table = self::$_table_name;
        $mongodb = \Mongo_Db::instance();
        return $mongodb->get($table);
}

public static function insertMongo($data) {
	$table = self::$_table_name;
        $mongodb = \Mongo_Db::instance();
        return $mongodb->insert($table, $data);
}
}

つぎにコントローラ
app/classes/controller/blog.php

<?php
class Controller_Blog extends Controller_Template {

public function action_index()
{
	$results = Model_Blog::findMongo();
	$this->template->title = 'Blog Index';
	$this->template->content = View::forge('blog/index')
		->set('results', $results);
}


public function action_insert() {
	$data = array(
		'title' => 'aaa', 
		'body' => 'eee', 
		'date' => date('Y-m-d H:i:s'), 
		'sub' => array(1,2,3)
	);
	Model_Blog::insertMongo($data);
	$this->response->redirect('/blog');
}
}

そしてview
app/views/blog/index.php

<p>Index</p>
<?php foreach($results as $post): ?>
	<br/>
	id: <?php echo $post['_id']; ?><br/>
	title: <?php echo $post['title']; ?><br/>
	body: <?php echo $post['body']; ?><br/>
	date: <?php echo $post['date']; ?><br/>
	sub:  <?php var_dump($post['sub']); ?>
	<hr>
<?php endforeach; ?>

これで、
/blog/insertにアクセスするとデータが保存されて、
/blogにアクセスすると保存データが見えます。subというカラムには配列データが保存されます。


#しかしなぜViewだけapp/classes/viewsじゃなくてapp/viewsにおくのだろうか。。。


明日は、@kenji_sさんの「FuelPHP での Migration の使い方」です!