BEARで始めるWebアプリケーション開発 その5「DBを扱うリソースの作り方を学んでみる」

前回までで、極めてシンプルな形のWebアプリケーションではありますが、BEARを使って動作するものを作成するところまで、一通りの流れを見てきました。

ただ、最初の紹介記事でも書いたように、Webアプリケーションが1画面で1機能だけを提供するような事はまず無い訳で、今回から数回に渡って、1画面(BEARで言うと"ページ")で複数のリソースを扱う場合について学習してみたいと思います。

で、どんな機能を追加するかって事なんですが、逆さ語は、文章の入力フォームの下に、最近変換された文章を表示するようにしているので、その機能を実装してみようと思います。

DBを使う場合のリソース作成を試してみる

実際のリソース設計・実装は次回に回すとして、今回はまずDBを使う場合のリソース作成の方法を学びます。

本家Wikiの中だと、デモの中のDBセレクトのページが比較的分かりやすいので、そちらを参考にしました。

DBの接続先の設定

上記ページには特に記載は無いのですが、アプリケーション全体に関わる設定は、"App/app.yml"に書かれていて、DBの接続先もそこで定義するようになっているので、自分の環境に合わせて定義を書き換えます。

App_Db:
  dsn:
    default: 'pgsql://user:pass@localhost/sakasago'
    slave:   'pgsql://user:pass@localhost/sakasago'
    test:    'pgsql://user:pass@localhost/sakasago'

BEARでは標準だとPEAR/MDB2が使われるので、対応しているRDBSであれば、DSNを適宜書き換えてやれば何でも利用できると思います。

また、最初からマスター/スレーブ構成が想定されていて、DSNを適宜設定してやれば、GETリクエストの時だけスレーブの方を読みに行くようになっています。

リソースの作成

以前のDBを使わないリソース作成の時のように、BEAR_Roクラスを継承してリソース作成してもいいんですが、DBアクセスのように全てのリソースで共通する処理がある場合は、App_Roクラスに抜き出して、App_Roクラスを継承してリソース作成する方が良いようです。

App_Roクラスはinit-appした時点で作成されて、特に設定する事無くそのまま使えるんですが、MySQLを使う事が想定されているようで、PostgreSQLだとそのままでは利用できませんでした。

以下のように、InnoDBを使うように設定しているところがあったので、そこをコメントアウトしたらPostgreSQLでも利用する事ができました。

        //$options['default_table_type'] = 'INNODB';

ここまで設定するとリソース内でSQLを発行する事ができるようになります。

ひとまず後々リソース実装する時に使う事になる、"sentences"というテーブルを作成しておいた上で、以下のような内容で、"App/Ro/sentences.php"というファイルを作成しました。

<?php
class App_Ro_Sentences extends App_Ro
{
    protected $_table = 'sentences';

    public function onInject (  )
    {
        parent::onInject();
        $this->_queryConfig['pager'] = 1; // DBページャ利用
        $this->_queryConfig['perPage'] = 5; // 1ページ毎のアイテム数
        $this->_query = BEAR::dependency('BEAR_Query', $this->_queryConfig, false);
    }

    public function onRead($values)
    {
        $sql = "SELECT * FROM {$this->_table}";
        $result = $this->_query->select($sql, array(), $values);
        return $result;
    }
}
?>

ポイントは、onInjectメソッドで、BEAR_Queryをインジェクトしているところですね。ここではページャを利用する設定をしています。これだけで、SQLに自動的にLIMIT文などを付与してくれる上に、テンプレートにページャ文字列をアサインするところまでやってくれるようです。

10件ぐらい適当にデータを投入しておいた上で、実際にリソースに読み込みリクエストを投げて、結果を見てみましょう。

$ bear read sentences
code
200
header
Array
(
    [totalItems] => 10
    [page_numbers] => Array
        (
            [current] => 1
            [total] => 2
        )

    [to] => 5
    [from] => 1
    [limit] => 5
    [_request] => read sentences
)
body
array (
  0 =>
  array (
    'id' => '0001',
    'created_at' => '2010-02-03 18:50:46.209538',
    'sentence' => 'テスト1',
    'status' => '0',
  ),
  1 =>
  array (
    'id' => '0002',
    'created_at' => '2010-02-03 18:50:51.773864',
    'sentence' => 'テスト2',
    'status' => '0',
  ),
  2 =>
  array (
    'id' => '0003',
    'created_at' => '2010-02-03 18:50:56.129688',
    'sentence' => 'テスト3',
    'status' => '0',
  ),
  3 =>
  array (
    'id' => '0004',
    'created_at' => '2010-02-03 18:51:00.626637',
    'sentence' => 'テスト4',
    'status' => '0',
  ),
  4 =>
  array (
    'id' => '0005',
    'created_at' => '2010-02-03 18:51:05.209228',
    'sentence' => 'テスト5',
    'status' => '0',
  ),
)

きちんとページングが行われている上に、ヘッダ部分にページングに関する情報が自動的に入っています。

このようにBEARのリソースは、"情報自体"と"情報に付随する情報"とが明確に分かれて出力されるようになっています。ヘッダ部は自分で自由に情報を追加する事もできるので、かなり柔軟にリソース設計を行う事ができるようになっていますね。

また、前回作成したリソースのように内部でゴリゴリ処理した結果を自分で返しても、今回のようにDBから取ってきた結果をそのまま返しても、リソースを呼び出す側から見ると全く区別無く利用できるというのも大きなポイントですね。

あと、他のメソッド(onCreate/onUpdate/onDelete)に関しては、デモページのサンプルコードを見れば書き方は分かるので、ここでは省略…。

という訳で、DB周りもかなり使い易く作られているので、DBを使ったリソースも非常に簡単に作る事ができました。

次回は?

次回は、新しく作るリソースを設計した上で、実装するところまでやる予定です。