过滤雄辩

时间:2020-01-11 14:23:48

标签: mysql laravel eloquent doctrine

我在项目中使用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'
        );
    }

以学说查询

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 个答案:

答案 0 :(得分:2)

要实现目标,可以同时使用when()whereHas()

$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提交后,它将电影限制为只有主类别为提交值的电影。


此外,仅供参考,使用Eloquent时无需添加from(...)方法。


一种限制行数的简单方法是将scopes添加到您的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);
})

答案 1 :(得分:0)

您可以使用whereHas方法,如文档所示:https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-existence

示例:

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();