thinkphp关联预载入支持带条件查询,通过闭包函数在`with`方法中定义过滤逻辑。具体做法是在调用模型关联查询时传入一个匿名函数,在该函数内使用`where`等链式方法设置条件,这样生成的sql会在子查询或连接查询中应用该限制,从而只返回满足条件的关联数据。

基础用法:如何在with中传递闭包
直接回答:在ThinkPHP 5/6/7中,可以通过将闭包作为参数传递给模型的`with`方法来为关联查询添加条件。例如,当我们需要获取用户及其最近发布的文章时,可以在闭包中使用`order`和`limit`来筛选。

$user = User::with(['posts' => function($query) {
$query->where('status', 1)->order('create_time', 'desc');
}])->find(1);
上述代码中,`User`模型定义了`posts`关联。在`with`方法中,我们传入了一个闭包。这个闭包接收一个`Query`对象实例,允许我们像普通查询一样使用`where`、`order`、`limit`等方法。最终生成的SQL会将这些条件应用到关联表的查询中。如果关联是`hasMany`,这通常转化为子查询;如果是`hasOne`或`belongsTo`,则可能转化为`LEFT JOIN`并带上`ON`条件。
立即学习“PHP免费学习笔记(深入)”;
进阶场景:处理多对多关联的条件过滤
直接回答:对于多对多(`belongsToMany`)关联,条件同样可以写在闭包中,但需要注意中间表的处理。通常我们过滤的是目标模型的数据,而不是中间表本身,除非有特殊需求。

$role = Role::with(['users' => function($query) {
$query->where('is_active', 1);
}])->find(1);
在这个例子中,`Role`模型与`User`模型是多对多关系。我们在闭包中对`User`模型添加了`is_active`等于1的条件。这意味着只有激活状态的用户会被加载到角色关联的集合中。需要注意的是,如果需要在中间表上添加条件,通常需要自定义关联查询或使用更底层的查询构造器,但在大多数业务场景下,过滤目标模型字段即可满足需求。
常见问题:闭包中的where条件是否影响主查询?
直接回答:不会。在`with`方法的闭包中设置的`where`条件仅作用于关联数据的查询,不会影响主模型(父级)的查询结果。主模型依然会按照其自身的查询条件返回所有匹配的记录,只是每条记录关联的子数据会根据闭包中的条件进行过滤。



















