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



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

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

这里有一个关于堆栈溢出的类似问题,但 OP 找到的解决方案是一种黑客攻击,在我的情况下不起作用,因为我需要它来为 varchars 工作。

注意:我意识到sortBy()接受第一个参数的闭包,但文档中没有解释这个闭包收到的参数(哪个"键"$key?),也没有明确说明闭包应该返回什么以确定排序顺序。(我假设它应该返回一个表示订单的整数,但我不知道如何使用多个NULL值为我工作。

sortBy方法接受要按升序排序的字段。因此,如果你有一个AppUser对象的集合,你可以传入first_name,这将按每个用户的名字排序。

如果您的逻辑更复杂,并且您想要对并非严格意义上的集合中每个项目的字段进行排序,则可以改为传递闭包。传递给闭包的第一个参数是实际项。您应该返回一个要从闭包中排序的值。假设在您的AppUser对象集合中,您希望按每个人名字的最后一个字母进行排序:

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

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

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

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

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

这应该允许你实现你的逻辑。为了确保null值被移动到最后,只需每次null您感兴趣的$a内容时返回1。同样,如果您从$b中感兴趣的内容null,则返回-1,如果您从$a$b中都null感兴趣,则返回0

最新更新