PHPの薄いDBライブラリ「Idiorm」を使ってみた

More than 1 year has passed since last update.

Idiormとは

PDOをそのまま使って業務システムを組んでいたのですが、大きくなるにつれてツラくなってきたので、ラッパーライブラリを探すことにしました。

以前はDoctrineを使っていたのですが、今の業務で使うには高機能すぎる感じがしたので、薄いライブラリを探していたところ、Idiormというのが良さそうだったので試してみることにしました。

$user = ORM::for_table('user')
    ->where_equal('username', 'j4mie')
    ->find_one();

$user->first_name = 'Jamie';
$user->save();

$tweets = ORM::for_table('tweet')
    ->select('tweet.*')
    ->join('user', array(
        'user.id', '=', 'tweet.user_id'
    ))
    ->where_equal('user.username', 'j4mie')
    ->find_many();

foreach ($tweets as $tweet) {
    echo $tweet->text;
}

http://j4mie.github.io/idiormandparis/
このソースは上記公式サイトの例ですが、なんとなくやっていることが分かると思います。

ドキュメント

http://idiorm.readthedocs.org/en/latest/index.html
こちらを見ればほぼすべての使い方が分かります。

インストール

https://github.com/j4mie/idiorm
こちらからダウンロードしてidiorm.phpを置いてrequireするだけです。1ファイルしか使わないので楽です。

Composerならば、

composer require j4mie/idiorm

でOKです。

デモ

demo.phpを開くとシンプルなコンタクトリストのデモが走ります。
SQLiteを使っていてテーブルも自動作成なので、何も用意する必要はありません。

使い方

基本的には静的メソッドfor_tableでテーブル名を指定するとORMオブジェクトが返ってくるので、それに対してメソッドをチェーンして行く感じです。

メソッド名

メソッド名はスネークケースとキャメルケースの両方に対応しています。例えばテーブルを指定するメソッドは「for_table」でも「forTable」でもOKという感じです。

※ただし、PHP 5.2ではキャメルケースでは動きませんでした。

カラムの指定

カラムを指定するときにはselectメソッドを使います。省略すると全カラムを取得します。

$users = ORM::for_table('user')
  ->select('name')
  ->find_many();

別名は第2引数で指定します。例えば「SELECT super_long_name AS name FROM user」の場合は、

$users = ORM::for_table('user')
  ->select('super_long_name', 'name')
  ->find_many();

複数カラムの場合は、チェーンを繋げるか、

$users = ORM::for_table('user')
  ->select('name')
  ->select('age')
  ->find_many();

select_manyを使います。

$users = ORM::for_table('user')
  ->select_many('name', 'age')
  ->find_many();

キモくないJOIN

一番上に提示した公式サイトのソースはJOINがキモイです。

->join('user', array(
  'user.id', '=', 'tweet.user_id'
))

ですが、キモくない書き方もできます。やった!

->join('user', 'user.id = tweet.user_id')

ただし、エスケープされないので取り扱い注意。JOIN自体が嫌なら同じ作者の作ったActive Record実装であるParisを使うと良いです。

複数のレコードを配列で取得する

内部ではほとんどORMオブジェクトで操作しますが、JSONで出力したいときなど、配列が欲しいときはfind_arrayを使います。

$users = ORM::for_table('user')
  ->order_by_asc('id')
  ->find_array();
$json = json_encode($users);

1レコードを配列で取得する

1レコードの返り値をそのまま連想配列で返すメソッドがありません(たぶん)。なので、find_oneで1レコードをORMオブジェクトで返して、as_arrayで配列に変換します。

$user = ORM::for_table('user')
  ->where('id', $id)
  ->find_one()
  ->as_array();

補足:カラム名がidなら以下のような省略記法も使えるようです。

$user = ORM::for_table('user')
  ->find_one($id)
  ->as_array();

複数レコードを同時に操作する

find_result_setを使うと複数レコードを同時に操作出来ます。
例:カラムnameが「太郎」のレコードを全て「花子」にする場合

$user = ORM::for_table('user')
  ->where('name', '太郎')
  ->find_result_set()
  ->set('name', '花子')
  ->save();

連想配列からの挿入・更新

連想配列にレコードの値が入っていて、テーブルにそのidのレコードがあればupdate、なければinsertという処理は以下のように書きました。

$in = [
  'id' => 4,
  'name' => '山田'
];
$user = ORM::for_table('user')->find_one($in['id']);
if (!$user) $user = ORM::for_table('user')->create();
$user->set($in);
$user->save();

レコードがなければcreateメソッドで新規作成しています。

最後に挿入されたレコードの連番値を取得

ID列が連番(AUTO_INCREMENT)のときに、挿入されたID値を取得したい場合はLAST_INSERT_ID()を使っても構いませんが、idメソッドを使うと簡単に取れます。

$user = ORM::for_table('user')->create();
$user->set($in);
$user->save();
$id = $user->id();

キャッシュ

ORM::configure('caching', true);

キャッシュが有効になり、同じSELECT文を発行した場合は、結果をメモリキャッシュから取得するようになります。

ORM::configure('caching_auto_clear', true);

INSERTやUPDATEでキャッシュをクリアします。

副作用はほとんど無いと思われますので、常にこの2行を設定しておくと良いでしょう。

注意点

複合主キーには対応していません。
これに気づかず急いでサロゲートキーを作った次第です。主キーの名前はデフォルトで「id」ですが、configメソッドでテーブルごとに変更することもできます。