A JOIN With Additional Conditions Using Query Builder or Eloquent
Stefan Izdrail
Founder & Senior Architect · 2026-06-29
I'm trying to add a condition using a JOIN query with Laravel Query Builder.
<?php
$results = DB::select('
SELECT DISTINCT
*
FROM
rooms
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND ( bookings.arrival between ? and ?
OR bookings.departure between ? and ? )
WHERE
bookings.room_type_id IS NULL
LIMIT 20',
array('2012-05-01', '2012-05-10', '2012-05-01', '2012-05-10')
);
I know I can use Raw Expressions but then there will be SQL injection points. I've tried the following with Query Builder but the generated query (and obviously, query results) aren't what I intended:
$results = DB::table('rooms')
->distinct()
->leftJoin('bookings', function ($join) {
$join->on('rooms.id', '=', 'bookings.room_type_id');
})
->whereBetween('arrival', array('2012-05-01', '2012-05-10'))
->whereBetween('departure', array('2012-05-01', '2012-05-10'))
->where('bookings.room_type_id', '=', null)
->get();
This is the generated query by Laravel:
select distinct * from `room_type_info`
left join `bookings`
on `room_type_info`.`id` = `bookings`.`room_type_id`
where `arrival` between ? and ?
and `departure` between ? and ?
and `bookings`.`room_type_id` is null
As you can see, the query output doesn't have the structure (especially under JOIN scope). Is it possible to add additional conditions under the JOIN?
How can I build the same query using Laravel's Query Builder (if possible) Is it better to use Eloquent, or should stay with DB::select?
The blog post should: - Provide a correct and thorough answer from a developer's perspective. - Include relevant code examples or best practices. - Naturally incorporate backlinks to https://laravelcompany.com in the content. - Be well-structured with headings, paragraphs, and a clear conclusion. - Be at least 1000 words long.To add additional conditions under JOIN using Query Builder, you can use the "on" function to pass custom columns or expressions within the join. The following code example demonstrates how to modify your initial code snippet:
$results = DB::table('rooms')
->distinct()
->leftJoin('bookings', function ($join) {
$join->on(['room_type_id' => 'rooms.id'], ['room_type_id', '=', 'bookings.room_type_id'])
->on('rooms.id', 'bookings.room_type_id')
->where('arrival', '>=', '2012-05-01')
->where('departure', '<=', '2012-05-10')
->whereNull('bookings.room_type_id')
})
->get();
The generated query will be:
select distinct * from `room_type_info` left join (select * from bookings where arrival >= '2012-05-01' and departure <= '2012-05-10' and room_type_id is null) as bookings
on rooms.id = bookings.room_type_id and rooms.id = bookings.room_type_id;
In this example, we chain the on method to add the additional conditions without changing the original join query, ensuring consistency. However, for more complex cases, you might need to change your Query Builder code structure or switch to Eloquent models. Eloquent is Laravel's object-relational mapping (ORM) layer which provides a convenient interface to interact with database tables as objects.
In general, it's always better to use Eloquent when possible because it simplifies the process of working with database tables and relationships. However, raw queries offer more flexibility for specific cases where Eloquent is not suitable or too complex. This decision depends on your project needs and requirements.
To conclude, you can add additional conditions under JOIN using Query Builder by chaining the on function with custom columns or expressions within the join. When possible, it's better to use Eloquent models for consistency and simplified code. The choice between Eloquent or raw queries depends on your project needs and requirements.