У меня есть много разных отношений между моими сотрудниками и группой. Я создал сводную таблицу, и все работает правильно с этим. Тем не менее, у меня есть столбец 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')
Кажется, работает.