如何使用 sortBy()、升序对 Laravel 集合进行排序,并将 NULL 值放在最后而不是第一个

How to sort a Laravel collection with sortBy(), ascending, and have NULL values placed last instead of first

Laravel 的 Collection class (v5.5) 有一个 sortBy() 方法,可以对所有内容进行排序,类似于使用 SQL ORDER BY 语句,除了有一个显着的区别:关系数据库在升序排序时会将 NULL 值放在末尾(或者至少 PostgreSQL 会这样做),但是 Laravel的 sortBy() 方法将 NULL 值放在首位。

那么在使用 Collection::sortBy() 方法时,如何让那些 NULL 值排在最后而不是排在前面? 请注意:我无法更改数据库查询本身!我唯一的选择是在 PHP 内对集合本身进行排序。在我的情况下,我绝对不能在数据库级别执行此操作。

有一个 但 OP 找到的解决方案是一种 hack 并且在我的情况下不起作用,因为我需要它为 varchars 工作。

注意:我知道 sortBy() 接受第一个参数的闭包,但是关于这个闭包接收的参数有 zero explanation in the documentation("key" 是 $key?) ,也没有明确说明闭包应该 return 来确定排序顺序。 (我假设它应该 return 一个代表顺序的整数,但我不知道如何使用多个 NULL 值使它对我有用。)

sortBy 方法接受要排序的字段,按升序。因此,如果您有一个 App\User 对象的集合,您可以传入 first_name 并按每个用户的名字排序。

如果您的逻辑更复杂,并且您想要对集合中每个项目的严格来说并非 字段 的内容进行排序,您可以改为传递闭包。传递给闭包的第一个参数是实际项目。您应该 return 一个要从闭包中排序的值。假设在 App\User 个对象的集合中,您想按每个人名字的最后一个字母排序:

$users->sortBy(function ($item) {
    return substr($item->first_name, -1);
});

第二个参数是key,也就是集合的key,或者它所代表的底层数组。如果你从数据库中检索了一个集合,这可能是一个数字索引,但如果你有一个不同的集合或者你决定通过用户的电子邮件地址重新键入集合(使用 keyBy) ,那就是通过了。

当涉及到将所有 null 值粘贴到排序结果集的末尾时,我建议使用 sort 方法而不是 sortBy。当您将闭包传递给 sort 时,它接受两个项目,代表您的集合中要排序的两个项目。对于 App\User 个对象的集合,每个项目都是 App\User 的一个实例。这使您可以完全控制两个对象的比较方式,从而完全控制顺序。

如果第一项被认为小于第二项,您应该 return -1(或负值),如果如果第一项被认为大于第二项,则两项将被视为相等且 1(或正值)。

$users->sort(function ($a, $b) {
    // Return -1, 0 or 1 here
});

这应该允许您实现您的逻辑。为确保 null 值移动到末尾,只要 return 1 每次您对 $a 感兴趣的内容是 null。同样,如果您对 $b 感兴趣的是 null、return -1,并且如果您对 $a 和 [=] 都感兴趣30=] 是 null, return 0.