どうしたらいいですか?
今回はこのような疑問に答えていきます。
結論:joinメソッドの引数にクロージャを渡す
結論から話すと、joinメソッドの引数にクロージャを渡せばOKです。
より高度なJOIN句を指定することもできます。そのためには、
join
メソッドの2番目の引数にクロージャを渡します。クロージャはIlluminate\Database\Query\JoinClause
インスタンスを受け取ります。これにより、"join"句に制約を指定できます。引用:公式ドキュメント
コード例を紹介
実現したいSQLが以下だとします。
SELECT
`users`.`name` AS `user_name`,
`messages`.*
FROM
`messages`
INNER JOIN
`users` ON `messages`.`user_id` = `users`.`id`
AND `messages`.`id` > '13'
この場合、laravel側のコードは次のようになります。
where()の部分で、2つ目のON句の条件を指定しています。
DB::table('messages')
->join('users', function ($join) {
$join->on('messages.user_id', '=', 'users.id')
->where('messages.id', '>', 13);
})
->select('users.name as user_name', 'messages.*')->get();
ちなみに、on句で「or」を使いたい場合は
->orOn('messages.pro_id', '=', 'users.id');
のように書いてあげればOKです。
【補足】
処理実行時に、SQLを確認できるように、デバッグモードをONにしておくといいです。Laravel8.Xでデバックモードを有効&デバッグバーを表示する方法【できない場合の解決方法も記載】で方法を紹介しています。
【注意点】ON句の条件に、変数を使うことはできない
本題に戻ります。
実は、先程のjoinメソッドを使った方法では、ON句で変数を使うことができません。
コード例は以下です。
//これだと失敗します
DB::table('messages')
->join('users', function ($join,$num) {
$join->on('messages.user_id', '=', 'users.id')
->where('messages.id', '>', $num); //ここで$numは使えません
})
->select('users.name as user_name', 'messages.*')->get();
じゃあ変数を使いたい場合は、どうすればいいかですが、結論から話すとSQLを直書きするといいです。
次のように書いてみましょう。
DB::select('SELECT `users`.`name` AS `user_name`, `messages`.* FROM `messages` INNER JOIN `users` ON `messages`.`user_id` = `users`.`id` AND `messages`.`id` > ?' , [$num]);
こうすることで、変数$numもon句で使用可能になります。