Framework: Remove Global Scopes from Eager Loaded Relationships

Created on 21 Sep 2016  路  12Comments  路  Source: laravel/framework

  • Laravel Version: 5.3.10
  • PHP Version: 7.*
  • Database Driver & Version: MySQL 5.7.12

    Description:

  • (forgive my ignorance if I'm mistaken) There is currently no way to remove a Global Scope off a relationship that you are eager loading onto a model.

Example:

  • \App\Models\Posts contains a global scope: ActiveScope that only displays active posts by default.
  • Posts belong to categories and categories have a relationship to pull in their posts.
  • Calling the typical: \App\Models\Categories::with('posts')->get(); leaves the global scope on posts
  • Doing: App\Models\Categories::withoutGlobalScopes()->with('posts')->get(); only removes global scopes from Categories, not posts.

Possible Suggestion:

A new method that can be called which strips global scopes off the relationship you request.

Most helpful comment

For the googlers, this now works:

return $this->belongsTo('App\Post')->withoutGlobalScope(ScopeClass::class);

All 12 comments

Sorry @ryanwhittaker but this repository is only for bug reporting :)

You can use the forums to ask questions, there's a much bigger chance that you receive an answer there.

Is it not considered a bug that there is no way I can remove the applied global scope from the relationship I'm eager loading?

I consider that a bug personally, as I have no way besides modifying it to be a local scope (not the functionality I wanted) to get the functionality I'm expecting.

Well it's considered a bug if you're sure about it, but since you're asking it's better that you make sure there's no way first and then submit a report.

Also please help us handle issues better by including the "Steps to reproduce" section of the issue, we try to replicate the problem in order to start looking for a fix, without this section the Issue takes a lot of time before any of us consider fixing it.

That makes sense, thanks @themsaid . Perhaps this would be an issue thats more fitting as a PR proposal?

Yeah, if you could find a fix and submit a PR that would be great :)

I think the following would be helpful:

return $this->belongsTo('App\Post')->withoutGlobalScopes();

For the googlers, this now works:

return $this->belongsTo('App\Post')->withoutGlobalScope(ScopeClass::class);

It's worth mentioning that withoutGlobalScope is not implemented in 4.2.
I was having an extra is null constraint mentioned here: https://github.com/laravel/framework/pull/7898 and what I finally did was to remove the eager loading...

Solution given above:

return $this->belongsTo('App\Post')->withoutGlobalScope(ScopeClass::class);

... has to be be done on model, when defining relation.

But, when you are pulling it building query, it does not work.

e.g.:

public function posts ()
{
    `return $this->hasMany('App\Post')->withoutGlobalScope(PostScopeClass::class);`
}

$this->user->with('posts')->withoutGlobalScope(PostScopeClass::class);

... does not seem to work.

Pity, because that is when you mostly need this.

Of course you always can create two relations, one with and one without scope:

public function postsNS ()
{
    `return $this->hasMany('App\Post')->withoutGlobalScope(PostScopeClass::class);`
}

public function posts ()
{
    `return $this->hasMany('App\Post');`
}

But that is rather a cumbersome solution.

You have access to the query of your relation like this:

$this->user
    ->with(['posts' => function ($query) {
        $query->withoutGlobalScopes([ActiveScope::class]);
    }])
    ->withoutGlobalScopes([PostScopeClass::class])
    ->get();

You have access to the query of your relation like this:

$this->user
    ->with(['posts' => function ($query) {
        $query->withoutGlobalScopes([ActiveScope::class]);
    }])
    ->withoutGlobalScopes([PostScopeClass::class])
    ->get();

Hey man, thank you, very very very much!

love it! Thanks!!

Was this page helpful?
0 / 5 - 0 ratings