Laravel Eloquent ORM中的自然排序

10
我该如何在'Eloquent ORM'中获取“自然排序”? 在表格中,我有一个名为'text'(字符串)的列。
正常排序:Model :: orderBy('text')
'value 1'
'value 12'
'value 23'  
'value 3'
'value 8'

I need this:

'value 1'
'value 3'
'value 8'
'value 12'
'value 23'  

有什么想法吗?
5个回答

13

您可以添加原始查询,然后像这样执行操作:

Model::orderBy(DB::raw('LENGTH(text), text'));

或者,在 Laravel 的现代版本中:

Model::orderByRaw('LENGTH(text), text');

好的。这两个文本是什么意思?一个是指行名称,另一个呢? - Sven van den Boogaart

6

Laravel也适用于这种方法:

$collection = $collection->sortBy('order', SORT_NATURAL, true);

我之前没有意识到sortBy函数可以接受第二个(或第三个)参数。这帮助我解决了Laravel 5.2集合排序的问题。尽管Laravel文档没有显示这个选项(https://laravel.com/docs/5.2/collections#method-sortby),但Collection.php文件中的sortBy函数确实显示它使用SORT_REGULAR作为默认的第二个参数(事后看来很有道理)。最终我选择了:Item::where($itemQueryArray)->with($modelName)->get()->sortBy($sortText, SORT_STRING | SORT_FLAG_CASE); - Keith DC

2
如果您使用PostgreSQL,您可以执行以下操作:
  1. Your migration

     public function up()
     {
         DB::unprepared(
         'create or replace function naturalsort(text)
         returns bytea language sql immutable strict as $f$
         select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || 
         length(r[1])::text || r[1]), \'SQL_ASCII\'),\'\x00\')
         from regexp_matches($1, \'0*([0-9]+)|([^0-9]+)\', \'g\') r;
         $f$;'); 
    }
    
    
    public function down()
     {
         DB::unprepared('DROP FUNCTION IF EXISTS naturalsort;');
     }
    
  2. In your model, you can add these scopes:

    public function scopeOrderByNatural(Builder $builder, string $column, string $direction = 'asc')
     {
         if (! in_array($direction, ['asc', 'desc'], true)) {
             throw new InvalidArgumentException('Order direction must be "asc" or "desc".');
         }
    
         return $builder->orderByRaw('naturalsort(' . $column . ') ' . $direction);
     }
    
    public function scopeOrderByNaturalDesc(Builder $builder, string $column)
     {
         return $builder->orderByNatural($column, 'desc');
     }
    
  3. And in your client code you can write:

Model::orderByNatural('text')->get();

或者反向排序

Model::orderByNaturalDesc('text')->get();

0

排序集合(SORT_NATURAL)

FROM

1 => "...\src\storage\avatars\10.jpg"
0 => "...\src\storage\avatars\1.jpg"
2 => "...\src\storage\avatars\100.jpg"
3 => "...\src\storage\avatars\1000.jpg"
4 => "...\src\storage\avatars\101.jpg"
5 => "...\src\storage\avatars\102.jpg"

0 => "...\src\storage\avatars\1.jpg"
1 => "...\src\storage\avatars\10.jpg"
2 => "...\src\storage\avatars\100.jpg"
3 => "...\src\storage\avatars\101.jpg"
4 => "...\src\storage\avatars\102.jpg"
5 => "...\src\storage\avatars\1000.jpg"

$natsort_collection = $collection->sortBy(null, SORT_NATURAL)->values();

// If you work with arrays: 
sort(...array of your data here..., SORT_NATURAL);

0

尝试这个 model::orderBy('text', 'asc')


你能详细说明一下吗? - Simas Joneliunas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接