Model Default Ordering: Assigning a Global Scope

Quite an often situation in real-life projects that you have to order lists by a certain condition. For example, countries/cities in alphabetical order everywhere. Is there a way to avoid adding “orderBy” every time we make a list for a dropdown? Apparently, it’s pretty easy – we can use Global Scopes.

Let’s say we have a model City with field name, and we need to order all the lists by name. Here’s what function we add to our model – we override a boot() method:

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

    // Order by name ASC
    static::addGlobalScope('order', function (Builder $builder) {
        $builder->orderBy('name', 'asc');
    });
}

Also we need to add this on top:


use Illuminate\Database\Eloquent\Builder;

Ok, so what do we see here? Method addGlobalScope is getting anonymous function as a parameter, where we actually tell the system what condition to add to all operations with Query Builder.

In reality, if you call City::all() from this point, it will actually execute this query:


select * from cities order by name asc

For more complex situations, you can change that anonymous function to a separate Scope class and pass it as a parameter, see official documentation here.

Like our articles?
Check out our Laravel online courses!

2 COMMENTS

  1. Very useful!
    Is there a way of sorting by ‘table_name’.’field’?
    I can’t manage to get the table name dynamically in the static method (need an instance, or hardcoded table name)

    • Workaround I’m using at the moment is to create an instance of the model to extract the table name:
      $tableName = (new Model())->getTable();

LEAVE A REPLY

Please enter your comment!
Please enter your name here