Skip to main content

Command Palette

Search for a command to run...

Laravel Query Scopes

Updated
2 min readView as Markdown

Global Scopes

Global scopes allow you to add constraints to all queries for a given model. Laravel's own soft delete functionality utilizes global scopes to only retrieve "non-deleted" models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints.

To assign a global scope to a model, you should override the model's booted method and invoke the model's addGlobalScope method. The addGlobalScope method accepts an instance of your scope as its only argument:

#Apply with Anonymous Global Scopes

 /**
     * * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::addGlobalScope('withoutGeneralTest', function (Builder $query) {
            $query->where([
                ['lession_id', '=', null],
                ['topic_id', '=', null],
                ]);
        });

        static::addGlobalScope('activeTest', function (Builder $query) {
            $query->where('test_status', self::TEST_ACTIVE);
        });
    }

#Removing Global Scopes


    /**
     * * show.
     *
     * @param  mixed $test
     * @return void
     */
    public function show(Test $test, $request)
    {
        $test->withoutGlobalScope('withoutGeneralTest');

        $test->loadMissing(['questions'=>function ($q) {
            $q->cacheFor(70)->select('test_id', 'quest_id', 'quest_name', 'quest_status', 'quest_content', 'quest_type', 'quest_level', 'quest_parent', 'quest_priority', 'questkind_id', 'quest_intro', 'quest_content');
        },

        'questions.questAnswers'=>function ($q) {
            $q->cacheFor(70);
        },

        'questions.questExplains'=>function ($q) {
            $q->cacheFor(70);
        },

        'memberHistories'=>function ($q) {
            $q->select('test_history_id', 'test_history_date', 'test_history_numanswer', 'test_history_numwrite', 'test_history_numskip', 'test_history_numcorrect', 'test_history_point', 'test_history_isfinish', 'test_total_time', 'test_id')
            ->byMember($this->member)
            ->orderLatest();
        },

        'favorites'=>function ($q) {
            $q->byMember($this->member);
        },
        ]);

        return $test;
    }

Local Scopes

Local scopes allow you to define common sets of query constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered "popular". To define a scope, prefix an Eloquent model method with scope. Scopes should always return a query builder instance:

 /**
     * * scopeByMember.
     *
     * @param  mixed $query
     * @param  mixed $member
     * @return void
     */
    public function scopeByMember($query, Member $member)
    {
        return $query->where('member_id', $member->member_id);
    }

    /**
     * * latest.
     *
     * @param  mixed $query
     * @return void
     */
    public function scopeOrderLatest($query)
    {
        return $query->orderBy('test_history_id', 'desc');
    }

#Utilizing A Local Scope

Once the scope has been defined, you may call the scope methods when querying the model. However, you should not include the scope prefix when calling the method. You can even chain calls to various scopes:

   /**
     * * getMemberTestHistory.
     *
     * @param  mixed $test
     * @return void
     */
    public function getMemberTestHistory(Test $test)
    {
        $selects = ['test_history_id', 'test_history_date', 'test_history_numanswer', 'test_history_numwrite', 'test_history_numskip', 'test_history_numcorrect', 'test_history_point', 'test_history_isfinish', 'test_total_time', 'test_id'];

        if (! $test->relationLoaded('memberHistories')) {
            return $test->memberHistories()
                          ->select($selects)
                          ->byMember($this->member)
                          ->orderLatest()
                          ->first();
        }

        return $test->memberHistories->first();
    }

More from this blog

Khang Nguyen

119 posts