#php #laravel #eloquent
Вопрос:
Я пытаюсь построить функцию фильтра, которая возвращает список обменов на основе функций, выбранных пользователем. Каждая функция имеет уникальный слиток, и $featureSlugs содержит массив этих слизней (строк).
$featureSlugs = ['security', 'mobile-app', '2FA'];
$exchanges = Exchange::whereHas('features', function ($q) use ($featureSlugs) {
$q->where('slug', $featureSlugs);
})->get();
Что чрезвычайно странно, этот запрос работает для 1 или 2 функций, но что-либо большее, чем 2, он перестает работать и больше не фильтруется.
Я хочу, чтобы фильтр становился все уже и уже, поэтому используйте несколько операторов where для каждой функции, возвращая только те обмены, в которых есть все функции, выбранные пользователем. Это код, который я пытаюсь, и он не работает, но я думаю, демонстрирует, что я пытаюсь сделать:
$exchanges = Exchange::whereHas('features', function ($q) use ($featureSlugs) {
foreach($featureSlugs as $featureSlug)
{
$q->where('slug', $featureSlug);
}
})->get();
Как я могу поместить несколько операторов where для каждой функции в массив?
Комментарии:
1. Моя рекомендация состоит в том, чтобы вы этого не делали, лучше заранее проверьте пули, а затем используйте условие
whereIn('slug', $array_of_slugs)
2. Проблема с Where заключается в том, что он вернет любой обмен по крайней мере с 1 функцией в списке, а не только обмены со всеми 3 функциями
Ответ №1:
Попробуйте сделать это таким образом.
$featureSlugs = ['security', 'mobile-app', '2FA'];
$exchanges = Exchange::whereHas('features', function ($query) use ($featureSlugs) {
$query->distinct()->whereIn('slug', $featureSlugs);
}, '=', count($featureSlugs))->get();
Комментарии:
1. Классно! Это работает! Я считаю, что это самое чистое решение.
2. Да, это так, и мне нравится, когда люди отмечают рабочее решение.
Ответ №2:
Ты идешь в правильном направлении. Вам просто нужно использовать whereIn
или orWhere
$exchanges = Exchange::whereHas('features', function ($q) use ($featureSlugs) {
$q->whereIn('slug', $featureSlugs);
// This one is not optimal of course
foreach($featureSlugs as $featureSlug) {
$q->orWhere('slug', $featureSlug);
}
})->get();
Ответ №3:
Вы можете сделать это таким образом:
$featureSlugs = ['security', 'mobile-app', '2FA'];
$exchanges = Exchange::whereHas('features', function ($q) use ($featureSlugs) {
foreach($featureSlugs as $featureSlug)
{
$q->where('slug', $featureSlug);
}
})-with(['features'=> function ($q) use ($featureSlugs) {
foreach($featureSlugs as $featureSlug)
{
$q->where('slug', $featureSlug);
}
}])->get();