获取两个集合中存在的所有对象

时间:2019-01-31 09:17:28

标签: laravel laravel-5 eloquent laravel-5.7

我正在构建一个Laravel页面,我想在该页面上显示课程列表。该页面上应该显示哪些课程,将由三个条件(所有条件都应为真)过滤:

  1. 该课程处于活动状态,即“ where('active',true)”。很简单。
  2. 课程是用户选择的曲目的一部分。模型是通过belongsToMany()建立的(这是多对多关系),因此我可以通过简单的$ track->教训来获得这些教训。
  3. 这是棘手的地方。有些课程仅对具有某些标题的用户可见(即,标题和课程之间有很多很多)。我可以使用Auth :: user()-> title->课程来获得具有正确标题要求的课程。

问题是我如何将所有这些融合在一起。到目前为止,我想出的最好的方法是:

$title = Auth::user()->title;
$lessons = Lesson::where('active', true)
    ->whereIn('id', $track->lessons->pluck('id'))
    ->where(function ($query) use($title) {
      $query->whereIn('id', $title->lessons->pluck('id'))->orWhere('limited_by_title', false);
    })
    ->get();

...这太丑陋了,显然不是最佳选择,并且(出于某种原因,我真的不明白)也无法正常工作(我没有从我的头衔中获得的课程)。现在已经挣扎了好几个小时,我觉得自己太复杂了,先采摘id,然后在whereIn()中使用它们可能不是这样做的好方法。

因此,我可以很容易地获得曲目中的课程集,并且可以获得属于该标题的课程集,但是如何获得这两个课程集中存在的所有对象?

3 个答案:

答案 0 :(得分:0)

关于在哪里使用“标题”关系的地方的信息

$title = Auth::user()->title;
$lessons = Lesson::where('active', true)
          ->whereIn('id', $track->lessons->pluck('id'))
          ->whereHas('titles',function ($query) use($title) {
                   $query->whereIn('id', $title->pluck('id')) 
                         ->orWhere('limited_by_title', false);
           })->get();

答案 1 :(得分:0)

使用whereHas()是您对获取ID的担忧的答案。 whereHas()不会运行其他查询来检索ID,而是将约束作为相关表的子查询附加到原始查询。

将查询细分为以下部分:

1:已回答

2:假设$ track->教训的倒数是$ lesson-> tracks,而$ track则来自您未包含的代码:

$lessons = Lesson::whereHas('tracks', function ($query) use ($track) {
            $query->where('id', $track->id);
        })

3:假设$ title->教训的倒数就是$ lesson-> titles:

$lessons = Lesson::where(function ($query) use ($title) {
                         $query->whereHas('titles', function ($query) use ($title) {
                             $query->where('id', $title->id);
                         })
                               ->orWhere('limited_by_title', false);
                     })

重新组合为一个:

    $track = ???;
    $title = Auth::user()->title;
    $lessons = Lesson::where('active', true)
                     ->whereHas('tracks', function ($query) use ($track) {
                         $query->where('id', $track->id);
                     })
                     ->where(function ($query) use ($title) {
                         $query->whereHas('titles', function ($query) use ($title) {
                             $query->where('id', $title->id);

                         })
                               ->orWhere('limited_by_title', false);
                     })
                     ->get();

如果这仍然不能提供您期望的结果,则可以通过将get()替换为toSql()来检查正在运行的完整查询。有时,从ORM(而不是SQL)作为起点可以使您走错路。有关调试和了解正在运行的查询的更多详细信息,可以启用查询日志记录:https://laravel.com/docs/5.7/database#listening-for-query-events

答案 2 :(得分:0)

首先是非常复杂的非常复杂。您的表结构需要进行认真的修改以使其更容易。

但是,考虑到您不想走这条路,可以使用 join

简化操作

假设您具有以下表结构:

  • 用户
  • 标题(具有user_id外键)
  • 课程(具有title_id外键)
  • 轨道(具有lesson_id外键)

    $trackName = $request->input('track_name');
    $title = Auth::user()->title;
    $lessons = Lesson::join('tracks', 'lessons.id', '=', 'tracks.lesson_id')
        ->join('titles', 'lessons.title_id', '=', 'titles.id')
        ->where('lessons.active', true)
        ->where('tracks.track_name', $trackName)
        ->where(function ($query) use($title) {
          $query->where('titles.id', $title->id)->orWhere('lessons.limited_by_title', false);
        });
    
    dd($lessons);
    

如果您的用户表和标题之间存在一对一的关系,那当然就是选择所有title_id,并使用whereIn而不是where进行titles.id查询。

我希望您对laravel框架有足够的了解,以理解和实现此解决方案。

抱歉,我没有足够的时间来校对或提供更多详细信息。 祝你好运!

如果您以后需要分页,请祝您好运:p我怀疑简单的->paginate()是否可以工作:D

我希望对您有帮助