はじめに
株式会社じげんの藤井です。
リフォームマッチングサイト リショップナビの開発を担当しています。
今年度の6月に現場配属され、半年ほどLaravelを使った開発に携わってきたので、
混同しがちなクエリビルダとEloquentとの相違点をまとめます。
これからLaravelを触り始める方の参考になれば幸いです。
クエリビルダとは?
LaravelのDB関連の機能として代表的なものに、クエリビルダがあります。
こちらはPHPを使ってSQL文を構築する仕組みで、メソッドチェーンでSQL関連のメソッドを並べてSQLを発行できるので、SQLがわかる人には直観的に理解しやすいという特徴があります。
具体的には、以下のように使用します。
use \Iluminate\Support\Facades\DB;
$posts = DB::table('posts')
->select('id', 'author_id')
->where('author_id', '10')
->orderBy('created_at', 'desc')
->get();
DBファサードのtableメソッドで、扱う対象となるDBのテーブルを指定しています。
select, where, orderByに関しては生のSQLと同じで、クエリをgetメソッドで実行し、結果を$postsに格納しています。
クエリビルダは、SQLインジェクションからアプリケーションを守る機能を備えています。(Eloquentも同様)
不正なSQL文が送られてきた場合、それをSQL文ではなく単なる文字列として扱う(エスケープする)ことで、DBに対する攻撃を防ぎます。
具体的には、PHPのプリペアドステートメントに対してPDOパラメータを後からバインディング(PHPのbindValue()のような処理が内部的に走る)することで、挿入されたパラメータが生SQLとして解釈され、意図しないSQL文が発行されてしまうのを事前に防いでいます。
Eloquentとは?
Laravelの機能として提供されているO/Rマッパーです。
RDBのテーブルとモデルを関連付ける機能を実現しており、PHPの書き方でDBを操作することを可能にします。
関連付ける具体的な方法としては、作成するモデルのクラス名を単数形で、DBのテーブル名をその複数形で作成することによって、自動的に紐づけることができます。
具体的には、以下のように使用します。
use App\Models\Post;
$posts = Post::where('author_id', 10)
->orderBy('created_at', 'desc')
->get();
Postモデルに紐づいた、DBのpostsテーブルから、author_idカラムが10のものを検索し、created_atカラムを降順に並べて返却したデータを$postsに格納しています。
また、DB間の差異をEloquentが吸収する(例えば、本来MySQLとPostgreSQLで異なる書き方をするべきであるところを、Eloquentが各々に適したSQLを自動的に発行してくれる)ため、アプリケーション側からDBの種類や仕様を意識しなくて良くなります。
「アプリケーションとDBを疎結合にする」と言い、保守性が高まります。
クエリビルダとEloquentの返り値の違い
クエリビルダとEloquentの大きな違いとして、返り値の形式があります。
クエリビルダの返り値
DB::table('posts')
->get();
stdClassのオブジェクト、またはそのCollectionとなります。
stdClassとはPHP標準で搭載されているClassで、プロパティやメソッドが一切定義されていないクラスです。
オブジェクトの代替として利用することがあるようです。
Eloquentの返り値
Post::all();
モデルオブジェクト、またはそのCollectionとなります。
Collectionの各要素がそのままPostクラスのインスタンスになっているため、foreachなどを使って個別の要素を取り出せば、クラス内に実装されたメソッドなども使えます。
クエリビルダとEloquentはどのように使い分ける?
Eloquentは、実は内部処理でクエリビルダを利用しています。そのため、クエリビルダで使用できるメソッドは全てEloquentでも使用可能です。
クエリビルダの方が適している場合
- パフォーマンスを重視する場合:一覧画面の実装など、多くのデータを取得する必要がある場合、よりパフォーマンスの良いクエリビルダが適しています。
- 複雑な条件を扱う場合:SQLに慣れていれば、クエリビルダはEloquentよりも発行されるSQLを把握しやすく、複雑な条件を適切に指定することができます。
Eloquentの方が適している場合
- 記述を簡潔にしたい場合:Eloquentではモデル同士にリレーションを貼ることができ、関連したモデルを簡単に呼び出すことが可能です。そのため、join句を使う必要のあるクエリビルダよりも相対的に記述が短くなります。
- クエリスコープを使いたい場合:上記の「記述を簡潔にする」と近い項目ですが、クエリの共通条件をメソッド化してしまい切り出すことで、同じクエリを繰り返し書かなくて良くなる「クエリスコープ」という機能がEloquentに実装されています。繰り返しを避けることができるようになるだけでなく、条件の一部が変更になった際に修正が1箇所で足りるといったメリットがあります。
こうして、両者を使い分けていくと良いのではないかと考えています。
## 〆
私自身、両者の違いを曖昧に理解していたまま使用していましたが、今回まとめてみることで大変勉強になりました。
皆さまの参考になれば幸いです。
今回は以上となります。