Laravel Query Builder入門!基本構文から実践的なクエリまで徹底解説
1. イントロダクション
Laravelでデータベースを操作する方法として、Eloquent ORMとQuery Builderの2つがあります。Eloquentはオブジェクト指向のアプローチを取り、モデルを通じてデータを操作します。一方で、Query BuilderはSQLに近い記述ができるため、柔軟かつ軽量なクエリの作成に適しています。
EloquentとQuery Builderの違い
特徴 | Eloquent ORM | Query Builder |
---|---|---|
記述スタイル | オブジェクト指向 | SQLに近い |
可読性 | 高い(Laravelらしい記述) | SQLライクで直感的 |
パフォーマンス | 比較的遅い(リレーション処理が多い) | 軽量で高速 |
使いどころ | 小〜中規模のデータ処理 | 大量データやカスタムクエリ |
Eloquentはリレーションが簡単に扱える一方で、Query Builderはより詳細なクエリを構築できるため、大規模なデータ処理や特定のパフォーマンスチューニングが必要な場合に役立ちます。
Query Builderを使うメリット
- SQLに近い記述が可能
- 生のSQLと似た書き方で、Laravelの便利機能も使える。
- Eloquentより軽量
- 必要最低限の処理でデータを取得できるため、パフォーマンスが向上。
- 柔軟なクエリ作成が可能
- カスタムクエリや複雑なデータ取得を効率的に記述できる。
このように、Query BuilderはEloquentよりも低レベルなデータ操作を可能にしつつ、SQLと同様の直感的な書き方を提供します。
2. Query Builderの基本構文
LaravelのQuery Builderを使うことで、SQLのようなクエリをシンプルに記述できます。このセクションでは、基本的なクエリの書き方を解説します。
2.1 データの取得(SELECT)
データを取得するには DB::table('テーブル名')
を使います。
use Illuminate\Support\Facades\DB;
// 全件取得
$users = DB::table('users')->get();
// 1件のみ取得
$user = DB::table('users')->where('id', 1)->first();
カラムを指定して取得
特定のカラムのみ取得する場合は select()
を使用します。
$users = DB::table('users')->select('id', 'name')->get();
2.2 条件付き取得(WHERE)
データをフィルタリングするには where()
を使います。
// IDが10のユーザーを取得
$user = DB::table('users')->where('id', 10)->first();
// 年齢が20以上のユーザーを取得
$users = DB::table('users')->where('age', '>=', 20)->get();
複数の条件を組み合わせることも可能です。
$users = DB::table('users')
->where('age', '>=', 20)
->where('status', 'active')
->get();
2.3 並び替え(ORDER BY)
データの並び順を指定するには orderBy()
を使います。
// 年齢順に昇順ソート
$users = DB::table('users')->orderBy('age', 'asc')->get();
// 名前順に降順ソート
$users = DB::table('users')->orderBy('name', 'desc')->get();
2.4 グループ化(GROUP BY)
特定のカラムごとにデータをグループ化する場合は groupBy()
を使用します。
$users = DB::table('users')
->select('age', DB::raw('count(*) as total'))
->groupBy('age')
->get();
2.5 ページネーション(ページ分割)
データをページごとに取得するには paginate()
を使います。
$users = DB::table('users')->paginate(10);
これにより、1ページに10件ずつ表示するデータが取得できます。
3. 実践的なクエリの例
ここでは、LaravelのQuery Builderを使って、より実践的なクエリを作成する方法を解説します。テーブルの結合(JOIN)、集計関数、サブクエリ など、実際の開発で役立つテクニックを紹介します。
3.1 テーブルの結合(JOIN)
データベースでは、複数のテーブルを結合して情報を取得することが一般的です。Query Builderでは、join()
や leftJoin()
を使って簡単にテーブルを結合できます。
INNER JOIN(内部結合)
join()
を使うと、指定したカラムが一致するデータのみ取得できます。
$orders = DB::table('orders')
->join('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', 'users.name as user_name')
->get();
このクエリは、orders
テーブルと users
テーブルを user_id
で結合し、注文情報とユーザー名を取得します。
LEFT JOIN(外部結合)
leftJoin()
を使うと、結合先のテーブルにデータがなくても、元のテーブルのデータは保持されます。
$orders = DB::table('orders')
->leftJoin('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', 'users.name as user_name')
->get();
ユーザー情報がない注文データも取得したい場合は、leftJoin()
を使用すると便利です。
3.2 集計関数(COUNT, SUM, AVG など)
Query Builderでは、SQLの集計関数をそのまま利用できます。
件数を取得(COUNT)
特定の条件に合うレコードの件数を取得するには count()
を使います。
$userCount = DB::table('users')->count();
合計を計算(SUM)
sum()
を使うと、数値の合計値を取得できます。
$totalSales = DB::table('orders')->sum('amount');
平均を取得(AVG)
avg()
を使うと、平均値を計算できます。
$averageAge = DB::table('users')->avg('age');
3.3 サブクエリを使ったデータ取得
サブクエリを使うことで、より複雑なデータ取得が可能になります。
最新の注文を取得するサブクエリ
最新の注文を取得するには、サブクエリを selectSub()
で使用できます。
$latestOrders = DB::table('users')
->select('users.id', 'users.name')
->selectSub(function ($query) {
$query->from('orders')
->whereColumn('orders.user_id', 'users.id')
->select('created_at')
->orderByDesc('created_at')
->limit(1);
}, 'latest_order')
->get();
このクエリでは、各ユーザーの最新の注文日時を取得しています。
まとめ
- JOIN を活用 して複数のテーブルを結合する
- 集計関数(COUNT、SUM、AVG など) を使って統計情報を取得する
- サブクエリ を利用して、より高度なデータ取得を行う
4. よくあるミスとエラーの回避方法
LaravelのQuery Builderは便利ですが、間違った使い方をすると意図しない結果になったり、パフォーマンスが悪化したりすることがあります。ここでは、よくあるミスとその対策 を解説します。
4.1 where()
の条件ミス
where()
を使う際、書き方を間違えると正しくデータが取得できないことがあります。
配列を使った where()
のミス
以下のように where()
で配列を渡してしまうと、意図した動作になりません。
// ❌ NG: これは動作しない
$users = DB::table('users')->where('id', [1, 2, 3])->get();
この場合、SQLでは id = (1,2,3)
のようになってしまい、構文エラーになります。
✅ 正しい書き方(whereIn()
を使用)
$users = DB::table('users')->whereIn('id', [1, 2, 3])->get();
4.2 join()
のデータ重複・NULL値問題
結合したデータの NULL 値に注意
leftJoin()
を使うと、結合先のテーブルにデータがない場合、NULLが含まれる可能性があります。
$orders = DB::table('orders')
->leftJoin('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', 'users.name as user_name')
->get();
この場合、users
テーブルに該当ユーザーがいない場合、user_name
が NULL
になります。
✅ NULL 値を考慮した対策
$orders = DB::table('orders')
->leftJoin('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', DB::raw("COALESCE(users.name, 'ゲスト') as user_name"))
->get();
COALESCE()
を使うことで、NULL の場合はデフォルト値("ゲスト")を設定できます。
4.3 SQLインジェクションのリスク
Query BuilderはデフォルトでSQLインジェクション対策が施されていますが、生のSQLを使う場合は注意が必要です。
❌ NG: 直接SQLを埋め込む(危険)
$name = $_GET['name']; // ユーザーからの入力
$users = DB::table('users')->whereRaw("name = '$name'")->get();
このコードでは、$name
に不正なSQL('; DROP TABLE users; --
など)が入力されると、データベースが破壊される可能性があります。
✅ 正しい書き方(バインディングを使用)
$users = DB::table('users')->whereRaw("name = ?", [$name])->get();
このように ?
プレースホルダを使うと、安全にクエリを実行できます。
4.4 N+1 問題と対策
N+1 問題とは?
where()
を繰り返し使ってデータを取得すると、無駄なクエリが大量に発生することがあります。
$users = DB::table('users')->get();
foreach ($users as $user) {
$orders = DB::table('orders')->where('user_id', $user->id)->get();
}
この場合、ユーザーの数だけ orders
テーブルにクエリが発行されるため、パフォーマンスが悪化します。
✅ 事前にデータを結合して取得
$users = DB::table('users')
->leftJoin('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'orders.id as order_id', 'orders.amount')
->get();
これにより、1回のクエリで必要なデータを取得でき、N+1問題を回避できます。
まとめ
- whereIn() を正しく使う(
where('id', [1,2,3])
はNG) - NULL値を考慮して
COALESCE()
を使う - SQLインジェクション対策として
?
を使ったバインディングをする - N+1問題を避けるために JOIN を活用する
これらのポイントを押さえておくことで、より安全で効率的なQuery Builderの使い方ができます。
5. まとめ
本記事では、LaravelのQuery Builderの基本的な使い方から、実践的なクエリの記述方法、さらにはよくあるミスの回避方法まで解説しました。
5.1 Query Builderのメリット
Query Builderを使うことで、以下のようなメリットがあります。
✅ SQLに近い記述ができる → 柔軟なクエリを簡単に作成可能
✅ Eloquentより軽量で高速 → 大量データの処理に適している
✅ 安全性が確保されている → バインディング機能でSQLインジェクションを防止
一方で、データのリレーションを扱う場合はEloquentの方が便利 なので、適材適所で使い分けるのが重要です。
5.2 EloquentとQuery Builderの使い分け
項目 | Query Builder | Eloquent |
---|---|---|
記述の簡潔さ | SQLライクな記述が可能 | オブジェクト指向で直感的 |
パフォーマンス | 軽量で高速 | モデルを利用するためオーバーヘッドあり |
適した用途 | 複雑なクエリ、大量データ処理 | リレーションを多用する場面 |
基本的には、シンプルなデータ取得はEloquent、複雑なクエリや大量データの処理にはQuery Builder を使うのがベストです。
5.3 LaravelでSQLを扱うスキルを磨こう!
Query Builderを使いこなすことで、Laravelのデータ操作の幅が大きく広がります。
ぜひ実際の開発で活用しながら、EloquentとQuery Builderを適切に使い分けるスキル を身につけていきましょう!