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

## Idiormとは

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

以前は[Doctrine](http://www.doctrine-project.org/)を使っていたのですが、今の業務で使うには高機能すぎる感じがしたので、薄いライブラリを探していたところ、Idiormというのが良さそうだったので試してみることにしました。

```php
$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メソッドを使います。省略すると全カラムを取得します。

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

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

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

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

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

select_manyを使います。

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

### キモくないJOIN

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

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

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

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


ただし、エスケープされないので取り扱い注意。JOIN自体が嫌なら同じ作者の作ったActive Record実装である[Paris](https://github.com/j4mie/paris)を使うと良いです。

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

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

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

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

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

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

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

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

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

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

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

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

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

```php
$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メソッドを使うと簡単に取れます。

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

### キャッシュ

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

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

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

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

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

## 注意点

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