按多个列对 Eloquent 集合进行排序的语法是什么?

2022-08-30 11:25:29

我知道在使用查询构建器时,可以使用

...orderBy('column1')->orderBy('column2')

但现在我正在处理一个集合对象。集合有方法,但我无法弄清楚如何使其适用于多个列。直观地说,我最初尝试使用与 相同的语法。sortByorderBy

sortBy('column1')->sortBy('column2)

但这显然只是按顺序应用排序,最终按列2排序,忽略列1。我试过了

sortBy('column1', 'column2')

但这会引发错误“asort() 期望参数 2 很长,给出字符串”。用

sortBy('column1, column2')

不会抛出错误,但排序似乎非常随机,所以我真的不知道它实际上做了什么。我查看了 sortBy 方法的代码,但不幸的是,我很难理解它是如何工作的。


答案 1

sortBy()采用闭包,允许您提供应用于排序比较的单个值,但您可以通过将多个属性连接在一起来使其成为复合值

$posts = $posts->sortBy(function($post) {
    return sprintf('%-12s%s', $post->column1, $post->column2);
});

如果您需要针对多个列的 sortBy,则可能需要对它们进行空格填充,以确保“ABC”和“DEF”位于“AB”和“DEF”之后,因此冲刺 (sprint) 为每列填充到列的长度(至少对于除最后一列之外的所有列)

请注意,如果可以在查询中使用 orderBy,则通常效率会高得多,这样集合在从数据库检索时即可立即排序


答案 2

我发现了一种不同的方法来做到这一点,使用雄辩的集合。它可能比填充字段工作得更好一些,或者至少更容易理解。我很想看看哪个表现更好,因为这个有更多的比较,但我不是为每个项目做。sort()sprintf()

$items->sort(
    function ($a, $b) {
        // sort by column1 first, then 2, and so on
        return strcmp($a->column1, $b->column1)
            ?: strcmp($a->column2, $b->column2)
            ?: strcmp($a->column3, $b->column3);
    }
);

推荐