seongbae's avatar

Disable global scope on model show?

I have a model called project which can be archived. Archived projects do not show on the index page and I do that by using global scope on the Project model:

class ArchiveScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('archived', false);
    }
}

then within the Project model, I have:

protected static function boot()
    {
        parent::boot();
  
        static::addGlobalScope(new ArchiveScope);
    }

However, I have a page where I'm showing all archived projects and users should be able to click on each project, view the content, and un-archive the project if needed. But due to the global scope, it will not display the project. When I go to an archived project at /projects/{project_id}, it gives me 404 not found error. How can I apply withoutGlobalScope to the show operation of Project?

Thank you.

Seong

0 likes
8 replies
ajithlal's avatar

From the documentation

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();

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

1 like
seongbae's avatar

Thanks. But how do I do that in the show() method?

public function show(Project $project)
    {
        return view('projects.show', compact('project'));
    }
guybrush_threepwood's avatar

The only workaround I see would be to disable route/model binding and manually select the project:

public function show($projectId)
    {
        $project = Project::withoutGlobalScope(AgeScope::class)->findOrFail($projectId);

        return view('projects.show', compact('project'));
    }
seongbae's avatar

That's what I thought...but was curious if there was a way without disabling route/model binding. Guess I'll go with that. Thanks!

1 like
ajithlal's avatar
ajithlal
Best Answer
Level 18

I hope you can achieve this using RouteServiceProvider. update your RouteServiceProviders boot method

public function boot()
    {
        parent::boot();

        Route::bind('project', function($id) {
            return \App\Project::withoutGlobalScopes()->findOrFail($id);
        });
    }
4 likes
UsmanBasharmal's avatar

You can do it

   Project::withoutGlobalScope(ArchiveScope::class)->get();
1 like

Please or to participate in this conversation.