#php #laravel #eloquent #many-to-many
#php #laravel #красноречивый #многие ко многим
Вопрос:
У меня есть две модели, которые имеют отношение «многие ко многим».
class User extends Model
{
function cars()
{
return $this->belongsToMany(Car::class);
}
}
class Car extends Model
{
function users()
{
return $this->belongsToMany(User::class);
}
}
Я хочу получить пользователей, которые использовали определенный набор автомобилей:
$car_selected = [1, 3, 6];
$users = User::when(count($car_selected) > 0, function ($q) use ($car_selected) {
$q->whereIn('cars.id', $car_selected);
})
->get();
Это дает слишком много результатов из-за условия «Где»; то, что я хочу, это «Где и» что-то.
Я пробовал это, но безуспешно.
$users = User::when(count($car_selected) > 0, function ($q) use ($car_selected) {
foreach($car_selected as $xx) {
$q->where( 'cars.id', $xx);
}
})
->get();
Как я могу получить всех пользователей, которые имеют отношение к автомобилям 1, 3 и 6?
Ответ №1:
Предоставленный вами код не имеет большого смысла, но, основываясь на вашем объяснении, вы хотите найти пользователя, который имеет отношение к автомобилям 1, 3 и 6. Использование whereIn()
дает вам пользователей с отношениями с автомобилями 1, 3 или 6.
Ваша попытка с несколькими where()
фильтрами не сработала бы, так как это означало бы поиск одной строки в сводной таблице с несколькими машинами, что, очевидно, было бы невозможно. Вместо этого вам нужно вложить несколько whereHas()
фильтров отношений в одну where()
группу, например:
$users = User::where(function ($q) use ($car_selected) {
foreach ($car_selected as $car) {
$q->whereHas('cars', function ($query) use ($car) {
$query->where('car_id', $car);
});
}
})
->with(['cars' => function ($q) use ($car_selected) {
$q->whereIn('car_id', $car_selected);
}])
->get();
Все это предполагает, что вы правильно настроили свои отношения и таблицы в соответствии со стандартами Laravel.
Демонстрационный код здесь: https://implode.io/anjLGG
Комментарии:
1. Да, это то, что я хочу .. да, это ответ для моего случая. Спасибо..
2. Извините за это. Я здесь почти новичок .. и я не могу найти способ принять ваш ответ.. Я тоже не вижу ✅. и в качестве ответа есть чей-то неправильный ответ. Я могу сказать, что я не принял этот неправильный код. Я прокомментировал событие, что это неверно. В любом случае извините за то, что причинил какую-то боль .. но не спешите принимать ваши. вот почему я прокомментировал ваш идентификатор и ответ.. Если вы дадите мне знать, как это исправить, я это сделаю. Спасибо.
Ответ №2:
Вы можете использовать whereHas
метод для запроса отношения:
use IlluminateDatabaseEloquentBuilder;
User::whereHas('cars', function (Builder $builder) use($car_selected)
{
$builder->whereIn( 'cars.id', $car_selected);
})->get();
Для получения дополнительной информации проверьте документ
Комментарии:
1. Спасибо за ответ.. Но теперь это то, чего я хочу. Использование ‘Where’ не может получить пересекающиеся строки. пожалуйста, внимательно прочитайте мой вопрос..
2. итак, что вы подразумеваете под «Это дает комбинацию из-за «условия Where». С какой проблемой вы сталкиваетесь?
Ответ №3:
как объяснил @miken32, мне нужно вложить несколько фильтров отношений whereHas () в одну группу where() .
@miken32 предложил следующее..
$users = User::where(function ($q) use ($car_selected) {
foreach ($car_selected as $car) {
$q->whereHas('cars', function ($query) use ($car) {
$query->where('car_id', $car);
});
}
})
->with(['cars' => function ($q) use ($car_selected) {
$q->whereIn('car_id', $car_selected);
}])
->get();
И я думаю, что следующего достаточно.
$users = User::where(function ($q) use ($car_selected) {
foreach ($car_selected as $car) {
$q->whereHas('cars', function ($query) use ($car) {
$query->where('car_id', $car);
});
}
})->get();
Спасибо.