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
相关产品推荐
相关产品推荐

