展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Laravel 递归关系排除指定分支教程

Laravel 递归关系排除指定分支教程

本教程旨在解决Laravel中处理递归关系时,如何有效地排除特定节点及其所有子孙节点的问题。通过利用Eloquent的递归关系加载能力、自定义的数组扁平化辅助函数以及whereNotIn查询,我们将展示一种在数据库层面高效过滤出非指定分支数据的方法,从而实现对复杂层级数据的精准控制。

本文目录

    Laravel 递归关系中排除指定分支的教程

    本教程旨在解决Laravel中处理递归关系时,如何有效地排除特定节点及其所有子孙节点的问题。通过利用Eloquent的递归关系加载能力、自定义的数组扁平化辅助函数以及`whereNotIn`查询,我们将展示一种在数据库层面高效过滤出非指定分支数据的方法,从而实现对复杂层级数据的精准控制。

    在构建具有层级结构的数据模型时,例如分类、评论回复或如本例中的兴趣爱好(hobbies),我们经常会遇到需要对这些层级数据进行特定过滤的需求。一个常见的场景是,给定一个父节点,我们需要获取所有不属于该父节点及其任何子孙节点的数据。本教程将详细介绍如何在Laravel中实现这一功能。

    数据模型与递归关系定义

    首先,我们假设有一个hobbies表,其结构包含id、name和parent_id字段,其中parent_id用于建立自引用关系,表示层级结构。

    CREATE TABLE hobbies (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(255) NOT NULL,
        parent_id INT NULL,
        FOREIGN KEY (parent_id) REFERENCES hobbies(id) ON DELETE CASCADE
    );

    在Laravel的Hobbies模型中,我们需要定义递归关系来方便地访问父级和子级:

    hasMany(Hobbies::class, 'parent_id');
        }
    
        /**
         * 定义父兴趣爱好关系。
         */
        public function parent_hobbies()
        {
            return $this->belongsTo(Hobbies::class, 'parent_id');
        }
    
        /**
         * 定义所有子孙兴趣爱好(递归子级)关系。
         */
        public function allsub()
        {
            return $this->sub_hobbies()->with('allsub');
        }
    
        /**
         * 定义所有祖先兴趣爱好(递归父级)关系。
         */
        public function allparent()
        {
            return $this->parent_hobbies()->with('allparent');
        }
    
        // ... 其他方法将在下面定义
    }

    allsub()方法是实现递归加载所有子孙节点的关键,它通过with('allsub')实现了自递归加载。

    排除指定分支的实现策略

    我们的目标是,给定一个兴趣爱好ID,获取所有不属于该ID及其所有子孙节点的兴趣爱好。实现这一目标的策略分为以下几步:

    1. 获取目标分支: 首先,查询指定ID的兴趣爱好,并利用allsub关系加载其所有子孙节点。
    2. 扁平化结果: 将包含多层嵌套关系的查询结果扁平化,转换为一个包含所有相关节点(包括目标节点及其所有子孙)的单一数组。
    3. 提取ID列表: 从扁平化后的数组中提取所有节点的id。
    4. 执行排除查询: 使用whereNotIn条件,从数据库中查询所有id不在上述列表中的兴趣爱好。

    为了封装这一逻辑,我们将在Hobbies模型中添加一个局部作用域(Local Scope)和私有辅助方法。

    1. 辅助方法:扁平化嵌套数组

    由于Eloquent的with递归加载会返回嵌套的数组结构,我们需要一个方法来将其转换为一个扁平的列表,以便提取所有节点的ID。

        /**
         * 辅助方法:将嵌套的Eloquent集合或数组扁平化为单一数组。
         * 仅保留非数组字段,并合并所有层级的数据。
         *
         * @param array|\Illuminate\Support\Collection $items
         * @return array
         */
        private function flattenRecursiveData($items)
        {
            $result = [];
            foreach ($items as $item) {
                // 如果是Eloquent模型实例,先转换为数组
                $itemArray = $item instanceof Model ? $item->toArray() : (array)$item;
    
                // 提取当前层级的非关系字段
                $currentLevelData = array_filter($itemArray, function ($value) {
                    return !is_array($value) && !($value instanceof \Illuminate\Support\Collection);
                });
                if (!empty($currentLevelData)) {
                    $result[] = $currentLevelData;
                }
    
                // 递归处理嵌套关系数据
                foreach ($itemArray as $key => $value) {
                    if (is_array($value) || $value instanceof \Illuminate\Support\Collection) {
                        $result = array_merge($result, $this->flattenRecursiveData($value));
                    }
                }
            }
            return $result;
        }

    方法说明:flattenRecursiveData方法迭代输入的数组或集合。对于每个元素,它首先提取非数组(非关系)的字段,将其作为一个独立的项添加到结果中。然后,它递归地处理所有嵌套的数组或集合(即关系数据),将它们的结果也合并到最终的扁平化数组中。

    2. 局部作用域:scopeIsNotLine

    现在,我们可以使用上述辅助方法来创建我们的局部作用域scopeIsNotLine。

        /**
         * 局部作用域:查询所有不属于指定ID及其子孙节点的兴趣爱好。
         *
         * @param \Illuminate\Database\Eloquent\Builder $query
         * @param int $id 要排除的根节点ID
         * @return \Illuminate\Database\Eloquent\Builder
         */
        public function scopeIsNotLine(Builder $query, int $id): Builder
        {
            // 1. 获取要排除的根节点及其所有子孙节点
            $hobbiesToExclude = Hobbies::with('allsub')->where('id', $id)->get();
    
            // 2. 扁平化结果,获取所有相关节点的数组表示
            $flattenedHobbies = $this->flattenRecursiveData($hobbiesToExclude);
    
            // 3. 提取所有要排除的节点的ID
            $excludeIds = collect($flattenedHobbies)->map(function ($item) {
                return $item['id'] ?? null; // 确保ID存在
            })->filter()->unique()->values()->all(); // 过滤空值,去重并重置索引
    
            // 4. 执行排除查询
            return $query->whereNotIn('id', $excludeIds);
        }

    局部作用域说明:

    1. Hobbies::with('allsub')->where('id', $id)->get():这行代码查询了指定$id的兴趣爱好,并通过allsub递归加载了其所有的子孙节点。
    2. $this->flattenRecursiveData($hobbiesToExclude):调用我们之前定义的辅助方法,将嵌套的Eloquent集合转换为一个扁平的数组。
    3. collect($flattenedHobbies)->map(...):使用Laravel的集合操作,从扁平化后的数组中提取所有id,并进行过滤、去重,确保得到一个干净的ID列表。
    4. return $query->whereNotIn('id', $excludeIds):这是核心的过滤操作。它会返回所有id不在$excludeIds列表中的兴趣爱好。

    使用示例

    现在,你可以在任何地方方便地调用这个局部作用域来获取所需的数据:

    get();
    
    // $filteredHobbies 将包含所有不属于ID为1的兴趣爱好及其子孙的数据
    foreach ($filteredHobbies as $hobby) {
        echo "ID: {$hobby->id}, Name: {$hobby->name}\n";
    }

    注意事项与性能考量

    • 数据量与深度: 如果你的层级结构非常深,或者每个节点有大量的子节点,with('allsub')的递归加载可能会导致生成非常大的查询结果集,占用较多内存。对于极端情况,可以考虑使用数据库的递归CTE(Common Table Expressions)功能,但这会使代码与数据库方言耦合。
    • 缓存: 对于不经常变化的层级数据,可以考虑将排除列表或最终结果进行缓存,以提高性能。
    • flattenRecursiveData的优化: flattenRecursiveData方法在处理大量数据时可能会有性能开销,因为它涉及多次数组合并和迭代。对于非常大的数据集,可能需要更优化的扁平化策略。
    • 额外条件: 在原始问题中提到了whereDoesntHave('is_archive')。你可以在isNotLine作用域之后链式调用其他查询条件,例如:
      $filteredHobbies = Hobbies::isNotLine($idToExclude)->whereDoesntHave('is_archive')->get();

    总结

    本教程提供了一种在Laravel中处理递归关系并排除特定分支的实用方法。通过结合Eloquent的递归关系加载、自定义的数组扁平化辅助函数以及whereNotIn查询,我们能够以清晰和相对高效的方式实现对复杂层级数据的精准过滤。这种方法在大多数应用场景下都非常有效,并且保持了Laravel Eloquent的优雅性。在面对极大数据量或深度时,可以进一步考虑数据库层面的优化方案。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。