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

Laravel中应用全局作用域时如何移除其他全局作用域?

Laravel子模型全局作用域移除父模型作用域的解决方案

你遇到的核心问题是全局作用域的执行顺序:父模型Assignment的InstitutionScope和not_template作用域会先于子模型Template的template作用域被应用到查询上,所以在子模型作用域里调用withoutGlobalScopes时,父作用域的条件已经被加到SQL里了,自然无法移除。

下面给出两种可行的解决方案:

方案一:在Template模型的boot方法中主动移除父模型的全局作用域

因为Template继承了Assignment,父模型的全局作用域会被自动继承,我们可以在Template的启动方法中,先移除不需要的父作用域,再添加自己的template作用域。

代码示例:

class Template extends Assignment
{
    protected static function boot()
    {
        // 先调用父类boot方法,确保trait的作用域被注册
        parent::boot();

        // 移除父模型的全局作用域
        static::removeGlobalScope(InstitutionScope::class);
        static::removeGlobalScope('not_template');

        // 添加Template自己的全局作用域
        static::addGlobalScope('template', function (Builder $builder) {
            $builder->where('is_shared', '=', true)
                ->orWhere(function($query) {
                    $query->where('institution_id', auth()->user()->institution_id)
                        ->where('is_template', true);
                });
        });
    }
}

方案二:让父模型的作用域在Template模型下自动跳过

修改InstitutionScope的apply方法,判断当前模型是否是Template的实例,如果是就不应用该作用域:

public function apply(Builder $builder, Model $model)
{
    // 如果当前模型是Template,跳过该作用域
    if ($model instanceof Template) {
        return;
    }
    $builder->where($model->getTable() . '.institution_id', auth()->user()->institution_id);
}

同时修改Assignment模型中not_template作用域的注册逻辑,同样判断模型类型:

class Assignment extends Model
{
    use BelongsToInstitution;

    protected static function boot()
    {
        parent::boot();

        // 仅在非Template模型中添加not_template作用域
        if (static::class !== Template::class) {
            static::addGlobalScope('not_template', function (Builder $builder) {
                $builder->where('is_template', '=', false);
            });
        }
    }
}

这样Template模型就不会继承父模型的两个全局作用域,直接使用自己的template作用域即可。

验证效果

修改后生成的SQL应该会变成:
select * from "assignments" where ("is_shared" = ? or ("institution_id" = ? and "is_template" = ?))
完全符合需求:共享模板所有机构可见,非共享模板仅所属机构可见。

内容的提问来源于stack exchange,提问作者Jacob Barrow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:06:13