Reputation: 143
Let's say we have many-to-many relationship for models Car and Driver:
class Car extends Model {...}
class Connection extends Model
{
public function car()
{
return $this->belongsTo('app\Car');
}
public function driver()
{
return $this->belongsTo('App\Driver');
}
}
class Driver extends Model {...}
Now I'd like to query for Cars which can be driven by John. With QueryBuilder this is quite simple:
$query = DB::table('cars')
->join('connections', 'cars.id', '=', 'connections.car_id')
->join('drivers', 'connection.driver_id', '=', 'drivers.id')
->where('drivers.name', 'like', 'John')->select('cars.*')->get();
This will generate a single SQL query which is more or less exactly would I'd expect.
The rest of the application uses Eloquent for DB querying and so I'd like to rewrite this part with Eloquent. I gave it multiple tries but I can't generate a single query with plain JOINs (not subqueries). Is it possible?
Upvotes: 0
Views: 2656
Reputation: 114
You can use whereHas eloquent function to get Cars which can be driven by John
$cars = Car::whereHas('drivers',function($query) use ($driver_name){
$query->where('name','like','%'.$driver_name.'%');
})->get();
for models you can use which @Idob write to his answer.
Upvotes: 1
Reputation: 1650
You can use the belongsToMany
relationship and delete your Connection
model.
Change your models to be:
class Car extends Model
{
public function drivers()
{
return $this->belongsToMany(Driver::class, 'connection');
}
}
class Driver extends Model
{
public function cars()
{
return $this->belongsToMany(Car::class, 'connection');
}
}
And query the driver's cars by:
$drivers = Driver::with('cars')
->where('name', 'like', 'John')
->get();
foreach ($drivers as $driver) {
$cars = $driver->cars;
}
Another small optimization is to follow Laravel's conventions for table naming and call the connection
table as car_driver
- than you would be able to remove the second parameter from the belongsToMany
mathod.
Upvotes: 0