makapaka's avatar

withoutGlobalScope not working as expected

I have a global scope setup in model boot:

static::addGlobalScope('group', function (Builder $builder) {
        $builder->where('group', '!=', 'true'); // NOT equal
    });

In controller I have some logic to determine whether to cancel the scope or not, and so I call a function on the model:

public function removeGroupScope()
{
    static::withoutGlobalScope('group');
}

It doesn't work as I expect: it still uses the group != true scope.

In the same function if I actually just add the global scope with different where clause it works - so I know the function runs, there must be a syntax error.

So this works, but don't think ideal:

    public function removeGroupScope()
{
    static::addGlobalScope('group', function (Builder $builder) {
         $builder->where('group', '=', 'true'); // EQUAL
    });
}

Any suggestions why specifically the withoutGlobalScope syntax doesn't work?

0 likes
6 replies
SilenceBringer's avatar

Hi @makapaka I think you use withoutGlobalScope wrong. Try something like

public function removeGroupScope()
{
    return $this->withoutGlobalScope('group');
}

then in your controller you can use it like

Model::removeGlobalScope()->get();
1 like
Wakanda's avatar

@makapaka

Removing Global Scopes If you would like to remove a global scope for a given query, you may use the withoutGlobalScope method. The method accepts the class name of the global scope as its only argument:


User::withoutGlobalScope(AgeScope::class)->get();

Or, if you defined the global scope using a Closure:

User::withoutGlobalScope('age')->get();

If you would like to remove several or even all of the global scopes, you may use the withoutGlobalScopes method:

see Laravel docs https://laravel.com/docs/7.x/eloquent#global-scopes

1 like
makapaka's avatar

thanks guys - I think I realise why it doesn't work - as an anonymous function, you can't call it that way.

Will have to either create it as a global scope or call it from the model as you suggest, thanks

piljac1's avatar

How about defining a local scope to remove that global scope ? (Not tested)

/**
 * Exclude the "group" global scope from the current query.
 *
 * @param \Illuminate\Database\Eloquent\Builder $query
 * @return \Illuminate\Database\Eloquent\Builder l
 */
public function scopeRemoveGroupScope($query)
{
    return $query->withoutGlobalScope('group');
}

Then you can use it as such :

YourModel::removeGroupScope();

// or if for some weird reason you want to add it at the end of your builder after some logic (same outcome as if you would put it at the beginning though)

YourModel::where('id', 1)->removeGroupScope();

In your original example you're not applying anything on the current query builder.

1 like
kokoshneta's avatar

@tigusigalpa I cannot reproduce that; it works just fine with ->find() for me.

In a Post class that has a PublishedScope applied globally, and where post 12345 is not published, this returns null in Tinker:

Post::find(12345);

While this returns the appropriate post:

Post::withoutGlobalScope(\App\Scopes\PublishedScope::class)->find(12345);

This is in Laravel 9.

Please or to participate in this conversation.