You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.8如何全局过滤关联隐藏Course的组件模型?

解决多组件模型关联Course的隐藏过滤重复逻辑问题

你可以通过创建可复用的Trait来统一处理所有关联Course的组件模型的过滤逻辑,避免在每个模型中重复编写whereHas和with的约束代码。具体实现步骤如下:

1. 创建全局过滤Trait

在项目中新建一个Trait文件(比如app/Traits/FilterHiddenCourse.php),把权限判断、Course过滤约束的逻辑封装进去:

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Request;

trait FilterHiddenCourse
{
    // 自动注册全局作用域
    public static function bootFilterHiddenCourse()
    {
        static::addGlobalScope('filter-hidden-course', function (Builder $builder) {
            $user = Request::user();
            
            // 仅当用户无查看隐藏课程权限时添加过滤
            if (!$user?->can('course/show-hidden-courses')) {
                // 获取当前模型与Course的关联路径(支持直接/间接关联)
                $courseRelation = (new static)->getCourseRelationPath();
                
                // 过滤掉关联Course处于隐藏状态的组件
                $builder->whereHas($courseRelation, function (Builder $q) {
                    $q->where('show', 1);
                });
                
                // 预加载Course关联时,仅加载显示状态的Course
                $builder->with([$courseRelation => function (Builder $q) {
                    $q->where('show', 1);
                }]);
            }
        });
    }

    // 默认关联路径为直接关联Course,子类可重写此方法适配间接关联
    protected function getCourseRelationPath()
    {
        return 'course';
    }
}

2. 在组件模型中引入Trait

对于每个需要关联Course过滤的组件模型(比如Material、Lesson、Assignment等),只需引入这个Trait即可,无需重复写过滤逻辑:

比如Material模型:

<?php

namespace App\Models;

use App\Traits\FilterHiddenCourse;
use Illuminate\Database\Eloquent\Model;

class Material extends Model
{
    use FilterHiddenCourse;

    // 模型关联定义
    public function course()
    {
        return $this->belongsTo(Course::class);
    }

    public function lesson()
    {
        return $this->belongsTo(Lesson::class);
    }
}

如果某个组件是间接关联Course(比如Material通过Lesson关联Course),只需在模型中重写getCourseRelationPath方法:

protected function getCourseRelationPath()
{
    return 'lesson.course';
}

3. 使用效果

之后查询任何引入该Trait的组件模型时,会自动完成:

  • 过滤掉关联Course处于隐藏状态的组件数据
  • 预加载Course关联时,仅返回显示状态的Course

原来的查询代码可以简化成:

$material = $materials_query->with(['lesson'])->whereIn('lesson_id', $lessons);

无需再手动添加whereHas和course关联的约束逻辑,所有逻辑都由Trait统一处理。

内容的提问来源于stack exchange,提问作者hend kagha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:36:24