【问题标题】:Laravel (8.x) Is there a better Eloquent query for this many-to-many filtering problem?Laravel (8.x) 这个多对多过滤问题有更好的 Eloquent 查询吗?
【发布时间】:2021-06-16 05:53:15
【问题描述】:

我有什么

movies多对多stars

movies多对多tags

studio一对多movies

我将studio 名称、star 名称和/或tag 名称作为可选查询字符串传递

我需要什么

  • 如果所有 3 个都作为参数传递,则选择所有 moviestagstarstudio
  • 选择所有moviestagstar(如果这两个作为参数传递)
  • 如果 moviesstarstudio 作为参数传递,则选择所有 movies
  • 如果moviestagstudio 作为参数传递,则选择所有movies
  • 选择所有moviestagstarstudio(如果有任何一个作为参数传递)
  • 基本上,简化此查询

我可能很愚蠢的代码

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

【问题讨论】:

    标签: php sql laravel eloquent laravel-8


    【解决方案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。我已经修好了谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2017-07-30
    • 2021-02-24
    • 2014-05-24
    • 2013-06-19
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2017-11-03
    相关资源
    最近更新 更多