Laravelでクエリビルダの使い方に関するメモ

4 回閲覧されました
みなさんこんにちは、jonioです。
クエリビルダに関してコードの書き方をすぐに忘れるので今回はメモとしてこの記事を残します。
新しく知った知識があるたびに追記します。
全てコントローラーの中身を記載します。
目次
Laravelの無料学習サイトを作りました
Laravelを勉強したい人向けの無料の学習サイトを作りました。
ここからリンクに飛べますのでぜひ利用してください。
クエリを条件に合わせて変える
ベースは同じクエリだけど「ある条件」の場合だけテーブルを検索する条件を追加したい場合があります。
その場合は下記の書き方をします。
$item1 = $request->input('item1');
$item2 = $request->input('item2');
$flag = $request->boolean('flag');
$result = DB::('tableA')->where('カラム1', $item1)
->when($flag, function ($q) {
$q->where('カラム2', $item2)
})
->first();
3行目が「ある条件」です。
これがtrueの時にテーブルを検索する条件を追加しますがそれが6行目〜8行目に該当します。
6行目のfunction以降は3行目の$flagがtrueの場合の条件追加です。
「$q->」を書くことで条件の追加ができます。
5行目の「->where(‘カラム1’, $item1)」に条件を追加するのは可能です。
join
あるテーブルに紐づくテーブルの情報も欲しい時に使います。
今回はテーブルAに紐づくテーブルBの情報も取得したい場合を考えます。
下記のコードで考えます。
$item1 = $request->input('item1');
$result = DB::table('tableA')->join('tableB', function ($join) {
$join->on('tableA.カラム1', '=', 'tableB.カラム1')
->on('tableA.カラム2', '=', 'tableB.カラム2');
})
->where('tableA.カラム1', $item1)
->select([
'tableA.*',
'tableB.カラム3'
])
->get();
4行目・5行目でテーブルAにテーブルBを紐づけています。
「tableA.カラム1」と「tableB.カラム1」は紐付けに使うカラムの指定をしています。
「->on」でテーブルAとテーブルBを紐づけていますが「->on」は1つでもいいし複数あってもいいです。(今は2つにしています)
7行目でtableAの絞り込みをしていますが条件をさらにつけることができます。
8行目・11行目は取得するカラムの指定をします。
クエリビルダを使う時はこの記述は必須です。
9行目の「tableA.*」の「*」は「全てのカラム」という意味になります。
取得したいカラムを記述します。
joinとleftJoinの違い
簡単に言うとテーブルAに紐づくテーブルBの情報がない時はテーブルAのレコードを取得しないのがjoinでテーブルBの情報がなくてもテーブルAのレコードを取得するのがjoinです。
具体的なコードで見ていきます。
joinの場合
ユーザーテーブル(users)とユーザーが書いた記事のテーブル(posts)で考えユーザーの情報を取得する時を考えます。
下記の記述をしたとします。
$results = DB::table('users')->join('posts', 'users.id', '=', 'posts.user_id')
->select('users.name', 'posts.title')
->get();
この場合は「’users.id’, ‘=’, ‘posts.user_id’」になる「posts.user_id」がある時だけusersテーブルのnameカラムとpostsテーブルのtitleカラムの値を取得します。
leftJoinの場合
$results = DB::table('users')->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->select('users.name', 'posts.title')
->get();
この場合は「’users.id’, ‘=’, ‘posts.user_id’」になる「posts.user_id」がある時はusersテーブルのnameカラムとpostsテーブルのtitleカラムの値を取得して「posts.user_id」がない時はusersテーブルのnameカラムの値を取得してpostsテーブルのtitleカラムの値はnullになります。
DB::raw
引数に生のSQLを使うことができます。
だからSQLを使わないといけなくなった時に使います。
サンプルコードは下記になります。
DB::table('users')->select(DB::raw('COUNT(*) AS cnt'))
->get();
selectRaw()
SELECT句に生のSQLを使うことができます。
サンプルコードは下記になります。
DB::table('users')->selectRaw('COUNT(*) as total_users')
->get();
DB::rawとselectRaw()の違い
slectRaw()はSELECT句でしか使うことができませんがDB::rawはWHERE句やGROUP BY句など色々な場合に使うことができます。
それならDB::rawを使えばselectRaw()はいらなくなりますがselectRaw()を使えば複数のカラムを一度に指定できます。(下記参照)
DB::table('user')->selectRaw('name, COUNT(*) as user_count')
->groupBy('name')
->get();
DB::rawを使うと下記になります。
DB::table('user')->select([
DB::raw('name'),
DB::raw('COUNT(*) as user_count')
])
->groupBy('name')
->get();
whereExistsとDB::raw(1)とwhereColumn
下記のコードで考えます。
DB::table('users')->whereExists(function ($q) {
$q->select(DB::raw(1))
->from('posts')
->whereColumn('posts.user_id', 'users.id');
})->get();
2行目の「DB::raw(1)」は「->from(‘posts’)」以下が成立するレコード全ての値を1として返すという意味です。
「whereExists(引数)」は引数が1の場合はtrueになるという意味です。
テーブルのレコードの変数を取得する時にwhereを使いますが例えば「where(‘posts.user_id’, ‘users.id’)」と記述すると「’users.id’」は文字列になりwhere句が成立しなくなります。
「’users.id’」を値として使いたい時に「whereColumn」と書けば「’users.id’」を値として使うことができます。
when
条件で絞り込みをしたい時に使います。
下記のコードで考えます。
$from = $request->input('from');
$to = $request->input('to');
DB::table('access_logs')->when($from && $to, function ($q) use ($from, $to) {
$q->whereBetween('visited_at', [$from, $to]);
})
->get();
whenの第一引数が絞り込みをする条件です。
条件を満たす時に第二引数以降が適用されます。
functionの外にある変数を使う時は「use ($from, $to)」の記述をしないといけません。
functionは下記の様にアロー関数の書き方もできます、この場合は「use ($from, $to)」の記述は必要ないです。
$from = $request->input('from');
$to = $request->input('to');
DB::table('access_logs')->when($from && $to, fn($q) => $q->whereBetween('visited_at', [$from, $to])) ->get();」