0

I usually sort the records by a column using global scopes on my model, but I need to order it by an attribute.

protected static function boot()
{
  parent::boot();
  static::addGlobalScope('order', function (Builder $builder) {
      $builder->orderBy('MyAttribute', 'dsc');
  });
}
Andronicus
  • 25,419
  • 17
  • 47
  • 88
  • 1
    Please be more clear and provide more information ... What attribute? How is your table structured? When do you need to sort by a this attribute? – ka_lin Jan 15 '20 at 20:22
  • Attribute i assume eloquent attribute? – mrhn Jan 15 '20 at 21:01

4 Answers4

0

You can make use of the method withoutGlobalScope to remove a scope from your query:

Model::withoutGlobalScope('order')->orderBy('attribute', 'order')->get();

Otherwise you can remove all global scopes:

Model::withoutGlobalScopes()->orderBy('attribute', 'order')->get();

You can read more about Removing Global Scopes here: https://laravel.com/docs/6.x/eloquent

Chin Leung
  • 14,621
  • 3
  • 34
  • 58
0

You mean smth like

//...
->orderByRaw('(updated_at - created_at) desc')
//...
Foued MOUSSI
  • 4,643
  • 3
  • 19
  • 39
0

I think your attribute is accessor, it is not the real column in database, so you cannot access it directly by query builder or eloquent builder without getting out of database.

However, you can access by collection or json. So if you want to sort the records, you need to use sortBy or sortByDesc on collection. And you need to get the result out of database. So you can sort them.

Model::all()->sortBy('MyAttribute');
Model::all()->sortByDesc('MyAttribute');
TsaiKoga
  • 12,914
  • 2
  • 19
  • 28
0

You have at three ways you can do this:

  • A) You can apply it to all queries.
  • B) Or you can create single scope in your model and call it on the query.
  • C) Or you can sort by however you directly on your query

A) You can apply it to all queries with:

  1. Create a new scope file locate at /app/Scopes/SortByScope.php

Then that file (SortByScope.php) should look like:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class SortByScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->orderBy('MyAttribute', 'DESC');
    }
}
  1. In your model include the call in your head
<?php

namespace App;

use App\Scopes\SortedOrderScope;

...rest of your model...
  1. Include the folling in your Model:
    /**
     * Apply to all queries.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();
        static::addGlobalScope(new SortByScope);
    }

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


B) Or you can create single scope in your model and call it on the query with:

  1. In your model input the folling method:
    /**
     * Scope a query to be sorted by MyAttribute
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeSortedByMyAttribute($query)
    {
        $builder->orderBy('MyAttribute', 'DESC');
    }
  1. Then in your Query use it with:
$results = App\MyModel::sortedByMyAttribute()->get();

-or-

$results = App\MyModel::where('foo', '=', 'bar')->sortedByMyAttribute();

https://laravel.com/docs/master/eloquent#local-scopes


C) Or you can sort by however you directly on your query with:

$results = App\MyModel::orderBy('MyAttribute', 'DESC')->get();
jeremykenedy
  • 4,150
  • 1
  • 17
  • 25
  • I tried using `scopeSortedByMyAttribute($query)` but i got an error `method illuminate database eloquent collection doesn't exist` – Ray Coder Oct 28 '20 at 14:53