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

时间:2018-01-17 20:46:00

标签: laravel sorting laravel-5 laravel-5.5 laravel-collection

Laravel的Collection类(v5.5)有一个sortBy()方法可以对所有类似的内容进行排序,如果您使用了SQL ORDER BY语句,除非有一个引人注目差异:关系数据库会在排序升序时(或至少PostgreSQL确实)将NULL值放在最后,但Laravel的sortBy()方法会先放置NULL值。

那么在使用NULL方法时,如何将这些Collection::sortBy()值排在最后而不是第一个? 请注意:我无法更改数据库查询本身!我唯一的选择是在PHP中对Collection本身进行排序。在我的情况下,我绝对不能在数据库级别这样做。

有一个similar question on Stack Overflow here但是OP找到的解决方案有点像黑客,并且在我的情况下不起作用,因为我需要它来为varchars工作。

注意:我意识到sortBy()接受第一个参数的闭包,但关于此闭包接收的参数有zero explanation in the documentation("键"是$key? ),也没有明确说出闭包应该返回什么以确定排序顺序。 (我假设它应该返回一个表示顺序的整数,但我不知道如何使用多个NULL值为我工作。)

1 个答案:

答案 0 :(得分:1)

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

如果您的逻辑更复杂,并且您希望对集合中每个项目的字段进行严格排序,则可以通过闭包。传递给闭包的第一个参数是实际项。您应该返回一个要从闭包中排序的值。让我们在您的App\User个对象集合中说,您希望按每个人的姓氏的最后一个字母排序:

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

第二个参数是键,它是集合的键或它代表的底层数组。如果您从数据库中检索了一个集合,这可能是一个数字索引,但如果您有一个不同的集合,或者您决定重新键入该集合,请说明用户的电子邮件地址(使用keyBy),那就是传递的内容。

如果要将所有null值保留在排序结果集的末尾,我建议使用sort方法而不是sortBy。将闭包传递给sort时,它会接受两个项目,表示要对您的集合中的两个项目进行排序。在收集App\User个对象的情况下,每个项目都是App\User的实例。这使您可以完全控制两个对象的比较方式,从而完全控制顺序。

如果第一项被认为小于第二项,则应返回-1(或负值),如果要认为这两项是相等的,则应返回0 1如果第一项被认为大于第二项,则为1}}(或正值)。

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

这应该允许你实现你的逻辑。为确保将null值移至最后,只要您对1感兴趣的任何内容$a,就返回null。同样,如果您对$b感兴趣的内容为null,则返回-1以及您对$a和{{{{}}感兴趣的内容1}}是$b,返回null