Laravel父子关联如何条件过滤

来源:建站技术作者:松松建站头衔:草根站长
导读:本期聚焦于小伙伴创作的《Laravel父子关联如何条件过滤》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Laravel父子关联如何条件过滤》有用,将其分享出去将是对创作者最好的鼓励。

在Laravel的Eloquent关联模型中,父子关联是非常常见的数据关系,比如分类模型Category和子分类模型之间的一对多关联,或者订单模型Order和订单项OrderItem的关联。实际开发中我们常常需要过滤关联数据,比如只获取父分类下状态为启用的子分类,或者只查询订单中价格大于100的订单项,下面介绍几种常用的实现方式。

Laravel父子关联如何条件过滤

基础关联定义

首先我们需要先定义好父子模型的关联关系,以分类和子分类为例,父分类模型Category的定义如下:

<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Category extends Model
{
    // 定义一对多关联,获取当前分类的所有子分类
    public function children()
    {
        return $this->hasMany(Category::class, 'parent_id');
    }
    // 定义反向关联,获取当前分类的父分类
    public function parent()
    {
        return $this->belongsTo(Category::class, 'parent_id');
    }
}

子分类使用的是同一个Category模型,通过parent_id字段区分父子关系,子分类的关联定义已经在上面的children方法中完成。

过滤父模型下的关联子数据

使用with方法配合闭包过滤

如果我们需要在查询父模型的同时,过滤加载的关联子数据,可以使用with方法的闭包参数,示例如下:

<?php
use AppModelsCategory;
// 查询所有父分类,并且只加载状态为1(启用)的子分类
$categories = Category::whereNull('parent_id')
    ->with(['children' => function ($query) {
        // 过滤子分类的条件,只获取状态为启用的子分类
        $query->where('status', 1);
    }])
    ->get();
foreach ($categories as $category) {
    // 这里的children只包含状态为1的子分类
    echo "父分类: {$category->name}, 启用的子分类数量: " . $category->children->count() . PHP_EOL;
}

这种方式会在查询父模型的同时,通过子查询过滤关联的子数据,不会把不符合条件的子分类加载到父模型的关联属性中。

使用whereHas过滤存在符合条件子数据的父模型

如果我们不仅需要过滤子数据,还需要只获取那些存在符合条件子数据的父模型,可以使用whereHas方法:

<?php
use AppModelsCategory;
// 查询所有存在状态为启用的子分类的父分类,并且加载这些启用的子分类
$categories = Category::whereNull('parent_id')
    ->whereHas('children', function ($query) {
        $query->where('status', 1);
    })
    ->with(['children' => function ($query) {
        $query->where('status', 1);
    }])
    ->get();

whereHas方法会筛选出至少存在一个符合条件的子分类的父模型,避免查询出没有符合条件的子分类的父模型数据。

过滤子模型对应的父模型

如果我们需要根据子模型的条件过滤对应的父模型,比如查询所有包含价格大于100的订单项的订单,可以使用反向关联的whereHas:

<?php
use AppModelsOrder;
use AppModelsOrderItem;
// 订单模型定义和订单项的关联
class Order extends Model
{
    public function items()
    {
        return $this->hasMany(OrderItem::class);
    }
}
// 查询所有包含价格大于100的订单项的订单
$orders = Order::whereHas('items', function ($query) {
    $query->where('price', '>', 100);
})->get();

多层关联的条件过滤

如果存在三层及以上的关联,比如分类、子分类、子分类下的商品,我们同样可以在with的闭包中嵌套关联查询:

<?php
use AppModelsCategory;
// 商品模型关联子分类
class Goods extends Model
{
    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}
// 查询父分类,加载启用的子分类,并且子分类下加载库存大于0的商品
$categories = Category::whereNull('parent_id')
    ->with(['children' => function ($query) {
        $query->where('status', 1)
            ->with(['goods' => function ($q) {
                $q->where('stock', '>', 0);
            }]);
    }])
    ->get();

注意事项

  • 使用with的闭包过滤时,只会影响关联数据的加载,不会影响父模型的查询结果,如果需要过滤父模型需要配合whereHas使用。
  • 如果关联数据量较大,建议合理添加索引,比如children关联中的parent_id和status字段可以建立联合索引,提升查询效率。
  • 避免在闭包中编写过于复杂的查询逻辑,复杂的过滤条件可以先封装成模型的作用域,提升代码可读性。

通过上述几种方式,我们可以灵活实现Laravel中父子关联数据的条件过滤,根据实际需求选择合适的查询方法即可。

Laravel父子关联条件过滤eloquent修改时间:2026-07-24 12:57:16

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。