【问题标题】:How to sort a Laravel collection with sortBy(), ascending, and have NULL values placed last instead of first如何使用 sortBy()、升序对 Laravel 集合进行排序,并将 NULL 值放在最后而不是第一个
【发布时间】:2018-01-17 20:45:59
【问题描述】:

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

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

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

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

【问题讨论】:

  • 请出示真实数据样本,以便我们为您找到可行的解决方案。

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


【解决方案1】:

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

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

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

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

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

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

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

这应该允许您实现您的逻辑。为确保null 值被移到末尾,只要每次您对$a 感兴趣的内容是null 时返回1。同样,如果您对$b 感兴趣的是null,则返回-1,如果您对$a$b 感兴趣的是null,则返回0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-12
    • 2016-08-04
    • 1970-01-01
    • 2017-09-12
    • 2016-02-07
    • 2011-09-25
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多