Josh
Josh

Reputation: 645

How to use orderBy() with model's method in Laravel

How can I use orderBy to order by a model's method?

Consider the model User and the method

public function fullName() {
    return $this->firstName . $this->lastName;
}

I want to do something like orderBy('fullName'). Is this possible? I know I can make equivalent code using Query Builder, but I want to keep my Model methods as they are.

Upvotes: 2

Views: 9449

Answers (3)

Alberto
Alberto

Reputation: 1

    $personas = Persona::select('*');
    $personas = $personas->addSelect(DB::raw('concat(nombre,\' \',apellido1,\' \',apellido2) as fullname'))
            ->orderBy('fullname', 'ASC')->paginate(K_LINEAS_X_PAGINA);

I couldn't make it work without the select('*')

Upvotes: 0

Josh
Josh

Reputation: 645

I've solved the problem with this solution:

$sorted = User::get()
    ->sortBy('full_name')  //appended attribute
    ->pluck('id')
    ->toArray();

$orderedIds = implode(',', $sorted);

$result = DB::table('user')
    ->orderByRaw(\DB::raw("FIELD(id, ".$orderedIds." )"))
    ->paginate(10);

I've appended fullName attribute to the model, to be used by sortBy. With this solution I was able to use orderBy to order by an appended attribute of the model, exactly what I wanted to do. So yes, it is possible. And also I was able to use pagination. Thanks to all who tried to help.

Upvotes: 1

Adam Rodriguez
Adam Rodriguez

Reputation: 1856

I think you have a few options here:

  1. Create a view in your database, which has the column fullName. Then change your model to use the view.
  2. Create a computed column fullName so that on insert if will use the values given from firstName and lastName.
  3. Use Laravel's Collection class. This class provides a sortBy method which you can use an attributes.

If you go with option 2, first define an attribute:

public function getFullNameAttribute()
{
    return $this->firstName . $this->lastName;
}

Then using Laravel's Collection:

$items = Model::all()->sortBy('FullName');

Note: The default option for sortBy is ascending, so if you wish to sort descending:

$items = Model::all()->sortByDesc('FullName');

You can read more about accessors here: https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor

Upvotes: 4

Related Questions