Как отсортировать значения NULL в последний раз, используя Eloquent в Laravel

У меня есть много разных отношений между моими сотрудниками и группой. Я создал сводную таблицу, и все работает правильно с этим. Тем не менее, у меня есть столбец sortOrder в таблице моих сотрудников, который я использую для определения порядка отображения. Сотрудник со значением 1 в столбце sortOrder должен быть первым, значение 2 должно быть вторым и так далее. (Или назад, если отсортировано по убыванию) Стол sortOrder представляет собой целочисленный столбец, который допускает нулевые значения.

Я настроил свою групповую модель для сортировки сотрудников по столбцу сортировки, но у меня возникла проблема. Сначала отображаются нулевые значения. Я пытался использовать ISNULL и подобные методы SQL вместо обычных «asc» или «desc», но я получаю сообщение об ошибке.

Вот код в моей модели группы:

class Group extends Eloquent { public function employees() { return $this->belongsToMany("Employee")->orderBy('sortOrder', 'asc'); } } 

И вот что я использую в контроллере для доступа к моей модели:

 $board = Group::find(6)->employees; 

Какая уловка в Laravel для сортировки значений NULL в последний раз?

 public function employees() { return $this ->hasMany('Employee') ->select(['*', DB::raw('IF(`sortOrder` IS NOT NULL, `sortOrder`, 1000000) `sortOrder`')]) ->orderBy('sortOrder', 'asc'); } 

Объяснение:
В заявлении IF решается проблема. Если значение NULL найдено, вместо sortOrder назначается некоторое большое число. Если найдено не значение NULL, используется реальное значение.

Просто добавьте знак минуса в поле и измените порядок на DESC.

 $q->orderBy(\DB::raw('-`sortOrder`'), 'desc'); 

Однако Laravel не принимает во внимание метод ISNULL но вы можете передать его как необработанный запрос и все еще использовать его, поскольку он более эффективен, чем если бы заявления и результаты оставались неизменными, если вы когда-либо выходите за пределы 1000000 сотрудников, :

 public function employees() { return $this->hasMany('Employee') ->orderBy(DB::raw('ISNULL(sortOrder), sortOrder'), 'ASC'); } 

Вместо того, чтобы полагаться на произвольное большое число, вы также можете:

 public function employees() { return $this ->hasMany('Employee') ->select(['*', DB::raw('sortOrder IS NULL AS sortOrderNull')]) ->orderBy('sortOrderNull') ->orderBy('sortOrder'); } 

Он имеет дополнительное преимущество при поддержке SQLite.

В Laravel 5.2 или выше просто вызывается orderByRaw . Вы даже можете сортировать агрегированное значение, а не столбцы. В следующем примере max_st может быть null если нет подмоделей.

 Model::where('act', '2') ->leftJoin('submodels', 'model.id', '=', 'submodels.model_id') ->select('models.*', DB::raw('MAX(submodels.st) as max_st')), ->orderByRaw('max_st DESC NULLS LAST'); 

Обходной путь для PostgreSQL

Для числовых типов:

 DB::table('t') ->select(['id', 'val']) ->orderBy(DB::raw("coalesce(val, 0)"), 'desc') 

Для типов текста:

 orderBy(DB::raw("coalesce(val, '')"), 'desc') 

Хитрость заключается в замене значений NULL в столбце сортировки на нуль (или пустую строку), чтобы его можно было отсортировать как обычное целочисленное (или текстовое) значение.

 ->orderBy('sortOrder', 'is', 'null')->orderBy('sortOrder', 'asc') 

Кажется, работает.