Как использовать orderBy() с методом модели в Laravel

Как я могу использовать orderBy для заказа по методу модели?

Рассмотрим модель User и метод

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

Я хочу сделать что-то вроде orderBy('fullName'). Это возможно? Я знаю, что могу сделать эквивалентный код с помощью Query Builder, но я хочу сохранить свои методы модели такими, какие они есть.


person Josh    schedule 23.11.2018    source источник
comment
короткий ответ, нет, это невозможно. orderBy() будет переведен в SQL Order BY, который не знает о вашем fullname().. в крайнем случае вы можете рассмотреть возможность использования DB::raw() для объединения вещей< /а>.   -  person Bagus Tesa    schedule 23.11.2018
comment
поэтому мне придется использовать DB:raw(), чтобы переписать все мои методы   -  person Josh    schedule 23.11.2018
comment
к сожалению, да, или вместо этого вы можете использовать трюк денормализации. создайте столбец с именем fullname и назначьте ему каждое сохранение модели.. о, подождите, у них есть orderByRaw на 5.7 - возможно, можно сделать что-то вроде ->orderByRaw('CONCAT(firstname, lastname)'), могу я узнать, какая версия вашего Laravel?   -  person Bagus Tesa    schedule 23.11.2018
comment
Я использую 5.7. Я хотел бы сохранить свои существующие методы, но, похоже, мне придется кодировать их с помощью DB:raw().   -  person Josh    schedule 23.11.2018
comment
нет, у тебя еще тот orderByRaw :(   -  person Bagus Tesa    schedule 23.11.2018


Ответы (3)


Я думаю, у вас есть несколько вариантов здесь:

  1. Создайте в своей базе данных представление со столбцом fullName. Затем измените свою модель, чтобы использовать представление.
  2. Создайте вычисляемый столбец fullName, чтобы при вставке if использовались значения, полученные из firstName и lastName.
  3. Используйте класс Collection Laravel. Этот класс предоставляет метод sortBy, в котором вы можете использовать атрибуты.

Если вы выберете вариант 2, сначала определите атрибут:

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

Затем с помощью коллекции Laravel:

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

Примечание. По умолчанию для sortBy используется возрастание, поэтому, если вы хотите отсортировать по убыванию:

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

Подробнее об аксессорах можно прочитать здесь: https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor

person adam    schedule 23.11.2018
comment
Я не могу использовать sortBy, потому что я использую нумерацию страниц, а в коллекциях нет нумерации страниц. - person Josh; 23.11.2018

Я решил проблему с этим решением:

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

Я добавил к модели атрибут fullName, который будет использоваться sortBy. С помощью этого решения я смог использовать orderBy для заказа по добавленному атрибуту модели, именно то, что я хотел сделать. Так что да, это возможно. А также я смог использовать пагинацию. Спасибо всем, кто пытался помочь.

person Josh    schedule 24.11.2018

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

Я не мог заставить его работать без выбора ('*')

person Alberto    schedule 16.12.2019