illuminate/database
私の携わったプロジェクトではORMが採用されないケースが多い。
メリットデメリットともにあるし、向き不向きもあるし、アレルギーを持ってる人がいたりするし、論争に興味もないのでそれ自体はいいのだけど、
たとえORMを使わない場合でも、クエリビルダだけは欲しいと思うことが多々ある。
「col1 = 'A' AND col2 = 'B'」のような同じ抽出条件が何度も出てきて、
それをベースにさらにwhere句を追加したSQLを書くような場合、
頻繁に出てくるwhere句を共通化したいのだけど、
文字列でSQLを組み立てているとだんだん訳が分からなくなってくる。
要はSQLの組み立てを構造的に行いたいのだ。
ORMはクエリビルダの機能を含んでいることが多いので、そこだけ使うことができないか調べてみた。
Doctrine2
PHPでいちばん有名なORM。Symfony2で使われている。
DQLというSQLライクではあるが独自の文法を覚えないとならない。
ちょっとヘビーすぎるし、ORM嫌いな人には採用されないだろうということでパス。FluentPDO
今回はパス。Idiorm
今回はパス。CakePHP3 cakephp/orm
クエリビルダだけ利用できたら使いやすそうなのだけど、
ORM/クエリビルダ部分として単品で使うことができず、
フレームワークのコアまで要求されるのでパス。illuminate/database
Laravelで使われている。
この中では一番hotそうなのでこれを試してみた。
今回は illuminate/database 5.2.7 を触ってみた。
Laravelではクエリビルダだけでなく Eloquent というORM層まで使うことが前提の内容なのだけど、基本的には Laravelのクエリビルダのドキュメント にクエリビルダのAPIも載っている。
括弧は関数で書くというのが特徴で、それ以外は直感的に使える感じ。
クエリビルダのみを使うにはこんな感じになる。(MySQLの場合)
$pdo = new \PDO($dsn); $iConnection = new \Illuminate\Database\Connection($pdo); $grammar = new \Illuminate\Database\Query\Grammars\MySqlGrammar(); $processor = new \Illuminate\Database\Query\Processors\MySqlProcessor(); $qb = new \Illuminate\Database\Query\Builder($iConnection, $grammar, $processor); $q = $qb->newQuery(); $q->from('users')->where('user_id', '>=', '100'); $q->orWhere('age', '>=', 20); var_dump($q->toSql(), $q->getBindings());
toSql()
でプレースホルダ(?
)付きのSQL文、getBindings()
で値が配列で取得できるので、これを PDO::prepare()
と PDOStatement::execute()
で実行すればいい。
(実行自体もクエリビルダでできるけど、ORM不採用プロジェクトなら固有のPDOラッパがあるはずなので)
ざっと使った感想
- SQLのステートメントがすべて小文字になる
- where, select など、部分的なSQLを得ることができない。
残念ながらwhere部分のみを得ることができないので、SQL全体をこれで構築することになる。 - selectカラムの追加は
addSelect()
でできるが、同一カラム名を追加すると重複してしまう。 - 集計系(count, max, min, avg, sum) は、即時にSQLが実行されてしまう。
今回の用途の場合は
selectRaw()
で書く必要がある。
$q = $qb->newQuery()->from('users')->selectRaw('COUNT(id) cnt');
- サブクエリは
whereRaw()
ですることになる。
つまり文字列の組み立てになってしまうということ・・。
$q = $qb->newQuery()->from('users') ->where('gender', '=', 'f') ->whereRaw('users.id IN (SELECT user_id FROM dept WHERE col1 = ?)', [1]);
- SELECT や WHERE に部分的に生クエリを書けるので、クエリビルダとしては自由度が高く、結構いろいろ書ける。
- 疑問符プレースホルダとなる
これくらいなら、ORM嫌いなチームでの採用もできるかもしれない。
でもサブクエリが文字列組み立てなら意味ないか。
FluentPDO と Idiorm も時間ができたら試してみよう。