0

I want to sort name of provinces in VietNam by utf-8 characters.

My Code

$provinces = Location::orderBy('name', 'ASC')
    ->whereNull('parent_id')->where('type', '1')
    ->pluck('name', 'id')
    ->toArray();

dd($provinces);

Result

array:5 [
  "06" => "Bắc Kạn"
  92 => "Cần Thơ"
  15 => "Yên Bái"
  11 => "Điện Biên"
  48 => "Đà Nẵng"
]

Expect

array:5 [
  "06" => "Bắc Kạn"
  92 => "Cần Thơ"
  11 => "Điện Biên"
  48 => "Đà Nẵng"
  15 => "Yên Bái"
]

Please help me.

Thanks so much!

AleksanderGD
  • 414
  • 5
  • 10
Hoang Dinh
  • 157
  • 1
  • 10

2 Answers2

1

The trouble is that you need to sort according to the viet collation, soooo

$arr = [
   6 => "Bắc Kạn",
  92 => "Cần Thơ",
  15 => "Yên Bái",
  11 => "Điện Biên",
  48 => "Đà Nẵng"
];

$c = new Collator('vi_VN');
$c->sort($arr);
var_dump($arr);

Output:

array(5) {
  [0]=>
  string(11) "Bắc Kạn"
  [1]=>
  string(10) "Cần Thơ"
  [2]=>
  string(11) "Đà Nẵng"
  [3]=>
  string(13) "Điện Biên"
  [4]=>
  string(9) "Yên Bái"
}

https://www.php.net/manual/en/collator.sort.php

Edit: Come to think of it, if all the data in the DB is Vietnamese you should change to a viet collation like utf8mb4_vi_0900_ai_ci so that your DB consistently orders things across the board. The following will list all available collations on your DB:

SHOW COLLATION WHERE Charset = 'utf8mb4';

Docs: https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html

Also: How to add collate to laravel query

Sammitch
  • 30,782
  • 7
  • 50
  • 77
  • Thanks for your feedback. But I received an error message: `Class 'App\Collator' not found`. Please help me! – Hoang Dinh Jun 14 '20 at 17:06
0

you could do it using php iconv

you can omit (orderBy here):

$provinces = Location::orderBy('name', 'ASC')->whereNull('parent_id')->where('type', '1')->pluck('name', 'id')->toArray();



 $sorted = array_values(Arr::sort($array, function ($value) {
            return iconv('UTF-8', 'ASCII//TRANSLIT', $value);
        }));

see:

https://stackoverflow.com/a/50990622/10573560

OMR
  • 11,736
  • 5
  • 20
  • 35