雄辩的 ORM 查询仅返回在其集合中具有特定模型的模型

Posted

技术标签:

【中文标题】雄辩的 ORM 查询仅返回在其集合中具有特定模型的模型【英文标题】:Eloquent ORM query to return only models that have specific models in their collections 【发布时间】:2014-05-14 21:22:35 【问题描述】:

我正在努力让 Eloquent ORM 产生我需要的结果。我有三个模型,作业、阶段和团队。

工作模式

public function phases()

    return $this->hasMany('Eloquent\Models\Phase', 'job_id', 'job_id');

阶段模型

public function job()

    return $this->belongsTo('Eloquent\Models\Job', 'job_id', 'job_id');


public function teams()

    return $this->hasMany('Eloquent\Models\Team', 'phase_id', 'phase_id');

团队模型

public function phase()

    return $this->belongsTo('Eloquent\Models\Phase', 'phase_id', 'phase_id');

当我执行查询时

$query = Eloquent\Models\Job::with("Phases.Teams");
$result = $query->get();

我有 40 个工作,其中包括 50 个阶段和 75 个团队。都很好。

当我执行查询时

$query = Eloquent\Models\Job::with(array("Phases.Teams" => function($query)

    $query->whereRaw("teams.team_member_quota > 5");
));

我得到一个包含 40 个工作的集合,其中包括 50 个阶段和 20 个团队。似乎我仍然获得了所有的 Jobs 和 Phases,但只有团队被过滤掉了。

我想收集只有团队的 team_member_quota > 5 的作业,并且其中只有团队的 team_member_quota > 5 的阶段,以及阶段只有团队的 team_member_quota > 5.

Eloquent ORM 可以做到这一点吗?

【问题讨论】:

【参考方案1】:

为此您需要whereHas,但由于它不适用于嵌套关系,因此您需要手动嵌套:

$query = Eloquent\Models\Job::whereHas('phases', function($query)

    $query->whereHas('teams', function ($q) 
        $q->whereRaw("teams.team_member_quota > 5");
    );
)
// ->with('phases.teams') // if you still need to load all the relations
;

这将获取具有相关PhasesJobs 具有> 5 个成员的Teams(如果需要,还可以加载这些作业的所有相关模型)


或者定义另一个hasManyThrough关系:

// Job model
public function teams()

   return $this->hasManyThrough('Team', 'Phase');


// then:
$query = Eloquent\Models\Job::whereHas('teams', function ($q) 
        $q->whereRaw("teams.team_member_quota > 5");
);

对于hasManyThrough,您需要确保所有模型都定义了$primaryKey,因为您似乎没有使用默认id

【讨论】:

谢谢,您的回答确实限制了那些包含 team_member_quota > 5 的团队的工作。但是,添加简单的 with('phases.teams') 导致这些工作中的所有阶段和团队被退回。但是,您的回答确实使我获得了正确的结果,非常感谢! 是的,当然,这就是您所要求的。如果您需要限制加载的团队也受到限制,只需在 with 方法中添加您之前拥有的代码。如果你只需要加载团队,没有阶段,那么使用with(['teams' => function($q) ...【参考方案2】:

这确实将作业限制为仅包含 team_member_quota > 5 的团队的作业

$query = Eloquent\Models\Job::whereHas('phases', function($query)

    $query->whereHas('teams', function ($q) 
    
        $q->whereRaw("teams.team_member_quota > 5");
    );
);

但是,添加“with”子句

$query->with('phases.teams');

仍会带回每个作业的所有阶段,无论它们是否包含符合条件的团队,以及这些阶段中的所有团队,无论他们的 team_member_quota > 5 与否。

我发现这个“with”子句有效

$query->with(array(
    "phases" => function($q1)
    
        $q1->whereHas('teams', function($q2)
        
            $q2->whereRaw('teams.team_member_quota > 5');
        );
    ,
    "phases.teams" => function($q)
    
        $q->whereRaw("teams.team_member_quota > 5");
    
));

仅提供包含符合条件的团队的阶段,以及结果中符合条件的团队。

【讨论】:

以上是关于雄辩的 ORM 查询仅返回在其集合中具有特定模型的模型的主要内容,如果未能解决你的问题,请参考以下文章

雄辩的 ORM 控制器或模型

雄辩的 ORM 查询——新手

我可以在一个地方(一个模型)使用雄辩的ORM和查询生成器吗?

Laravel 5 具有雄辩的关系回调函数返回错误记录

如何分配自定义 SQL 查询,该查询返回行集合作为 ORM 模型的属性

如果急切加载的值具有价值,则仅返回雄辩的结果?