Laravel (8.x) 这个多对多过滤问题有更好的 Eloquent 查询吗?
Posted
技术标签:
【中文标题】Laravel (8.x) 这个多对多过滤问题有更好的 Eloquent 查询吗?【英文标题】:Laravel (8.x) Is there a better Eloquent query for this many-to-many filtering problem? 【发布时间】:2021-06-16 05:53:15 【问题描述】:我有什么
movies
多对多stars
movies
多对多tags
studio
一对多movies
我将studio
名称、star
名称和/或tag
名称作为可选查询字符串传递
我需要什么
如果所有 3 个都作为参数传递,则选择所有movies
和 tag
和 star
和 studio
选择所有movies
和tag
和star
(如果这两个作为参数传递)
如果 movies
和 star
和 studio
作为参数传递,则选择所有 movies
如果movies
和tag
和studio
作为参数传递,则选择所有movies
选择所有movies
和tag
或star
或studio
(如果有任何一个作为参数传递)
基本上,简化此查询
我可能很愚蠢的代码
public function index(Request $request)
$movies = Movie::with('stars')->with('tags')->with('studio');
// all matches
// if all params are present
if ($request->star && $request->tag && $request->studio)
$movies->whereHas('stars', function ($query) use ($request)
$query->where('name', $request->star);
)->whereHas('tags', function ($query) use ($request)
$query->where('name', $request->tag);
)->whereHas('studio', function ($query) use ($request)
$query->where('name', $request->studio);
);
// star and tag with no studio
if ($request->star && $request->tag && !$request->studio)
$movies->whereHas('stars', function ($query) use ($request)
$query->where('name', $request->star);
)->whereHas('tags', function ($query) use ($request)
$query->where('name', $request->tag);
);
// star and studio with no tag
if ($request->star && !$request->tag && $request->studio)
$movies->whereHas('stars', function ($query) use ($request)
$query->where('name', $request->star);
)->whereHas('studio', function ($query) use ($request)
$query->where('name', $request->studio);
);
// studio and tag with no star
if (!$request->star && $request->tag && $request->studio)
$movies->whereHas('tags', function ($query) use ($request)
$query->where('name', $request->tag);
)->whereHas('studio', function ($query) use ($request)
$query->where('name', $request->studio);
);
// any one matches
if ($request->star || $request->tag || $request->studio)
$movies->whereHas('stars', function ($query) use ($request)
$query->where('name', $request->star);
)->orWhereHas('tags', function ($query) use ($request)
$query->where('name', $request->tag);
)->orWhereHas('studio', function ($query) use ($request)
$query->where('name', $request->studio);
);
return response($movies->paginate(20));
【问题讨论】:
【参考方案1】:我想你需要的是这样的:
public function index(Request $request)
$movies = Movie::with('stars')->with('tags')->with('studio');
// all matches
// tag
if ($request->tag)
$movies->whereHas('tags', function ($query) use ($request)
$query->where('name', $request->tag);
);
// star
if ($request->star)
$movies->whereHas('stars', function ($query) use ($request)
$query->where('name', $request->star);
);
// studio
if ($request->studio)
$movies->whereHas('studio', function ($query) use ($request)
$query->where('name', $request->studio);
);
return response($movies->paginate(20));
这样你只过滤你的关系,如果它提供了它的键。
【讨论】:
啊,这是我最初的方法,然后我把事情复杂化了,谢谢伙计,这行得通。这是方法。但在演播室里也应该是whereHas
而不是orWhereHas
,对吧?
Np :) 是的,它应该是whereHas
。我已经修好了谢谢:)以上是关于Laravel (8.x) 这个多对多过滤问题有更好的 Eloquent 查询吗?的主要内容,如果未能解决你的问题,请参考以下文章
Laravel:具有 whereHas 和多对多关系的全局范围