Фильтр красноречивый - PullRequest
0 голосов
/ 11 января 2020

Я использую laravel для проекта. Я хочу создать конечную точку, которая фильтрует и ищет модель Film и возвращает коллекцию фильмов, которые соответствуют выбранным параметрам фильтра, которые Options, Location and Age Rating будут выбраны пользователем.

Я создал запрос о том, как я бы изначально присоединился к таблицам в symfony (надеюсь, это правильно), но я не уверен в том, как настроить его, чтобы он был более Laravel или красноречивым.

Модель фильма

    public function location(): BelongsTo
    {
        return $this->belongsTo(Location::class);
    }

    public function options(): BelongsToMany
    {
        return $this->belongsToMany(
            Option::class,
            'film_options',
            'film_id',
            'option_id'
        );
    }

 public function ageRatings(): BelongsToMany
    {
        return $this->belongsToMany(
            AgeRating::class,
            'film_age_ratings',
            'film_id',
            'age_rating_id'
        );
    }

Запрос в Doctrine

Select *
        From films  f
        Join film_options fo on f.id = fo.film_id
        Join options o on o.id = fo.option_id 
        Join film_age_ratings fa on f.id = fa.film_id
        Join age_ratings a on a.id = fa.age_rating_id
        Join location l on l.id = p.location_id

Как мне написать этот запрос в laravel?

Ответы [ 2 ]

1 голос
/ 11 января 2020

Чтобы достичь того, что вам нужно, вы можете использовать смесь когда () и гдеHas () :

$films = Film
    ::when($request->input('first'), function ($query, $first) {
        $query->whereHas('options', function ($query) use ($first) {
            $query->where('first', $first);
        });
    })
    ->when($request->input('second'), function ($query, $second) {
        $query->whereHas('options', function ($query) use ($second) {
            $query->where('second', $second);
        });
    })
    ->when($request->input('age'), function ($query, $age) {
        $query->whereHas('ageRatings', function ($query) use ($age) {
            $query->where('age', $age);
        });
    })
    ->when($request->input('country'), function ($query, $country) {
        $query->whereHas('locations', function ($query) use ($country) {
            $query->where('country', $country);
        });
    })
    ->when($request->input('city'), function ($query, $city) {
        $query->whereHas('locations', function ($query) use ($city) {
            $query->where('city', $city);
        });
    })
    ->orderBy('updated_at', 'desc')
    ->get();

По сути, что выше делает, говорит, что когда вы отправили непустое значение, он добавит предложение where к запросу для этого отношения
, например, если отправлено main, ограничит фильмы только теми, у которых есть категории, когда основной является отправленное значение.


Кроме того, просто для справки, вам не нужно добавлять метод from(...) при использовании Eloquent.


Простой способ ограничения числа линий добавит областей к вашей Film модели, например

В вашей Film модели:

public function scopeHasMain($query, $main)
{
    $query->whereHas('options', function ($query) use($first) {
        $query->where('first', $first);
    });
}

Тогда ваш метод when() будет :

when($request->input('first'), function ($query, $first) {
    $query->hasFirst($first);
})
0 голосов
/ 11 января 2020

Вы можете использовать метод whereHas, как показано в документации: https://laravel.com/docs/5.8/eloquent-relationships#querying -relationhip-существование

Пример:

use Illuminate\Database\Eloquent\Builder;

//...

$optionIds = [/* Option ids to filter by */];
$films = Film::whereHas('options', function (Builder $query) use ($optionIds) {
    $query->whereIn('options.id', $optionIds);
})->get();
...