Đồng bộ mã hóa tiếng Việt có dấu là điều phải làm để có được kết quả thống kê chính xác

Phiên bản nâng cấp của bộ chuyển đổi mã hex tiếng Việt đã có ở bài viết này: Các hàm PHP chuyển đổi ký tự tiếng Việt từ dạng mã hex ít phổ biến về dạng phổ biến và ngược lại (v1.2)

Trong bài viết trước, tôi có nói về bộ chuyển mã hóa tiếng Việt để nó có bộ mã hóa UTF-8 đồng nhất, đây chính là hàm xử lý việc đó:

function chuyen_ma_hoa($str) {    
$phothong = array();  // tạo mảng chữ cái mã hóa phổ biến
$itdung = array();  //tạo mảng chữ cái mã hóa ít dùng
    
$phothong[0]='ỳ';
$itdung[0]='ỳ';
   
$phothong[1]='ọ';
$itdung[1]='ọ';

$phothong[2]='á';
$itdung[2]='á';

$phothong[3]='ầ';
$itdung[3]='ầ';

$phothong[4]='ả';
$itdung[4]='ả';

$phothong[5]='ấ';
$itdung[5]='ấ';

$phothong[6]='ờ';
$itdung[6]='ờ';

$phothong[7]='ễ';
$itdung[7]='ễ';

$phothong[8]='à';
$itdung[8]='à';

$phothong[9]='ạ';
$itdung[9]='ạ';

$phothong[10]='ằ';
$itdung[10]='ằ';

$phothong[11]='ệ';
$itdung[11]='ệ';

$phothong[12]='ế';
$itdung[12]='ế';

$phothong[13]='ý';
$itdung[13]='ý';

$phothong[14]='ộ';
$itdung[14]='ộ';

$phothong[15]='ậ';
$itdung[15]='ậ';

$phothong[16]='ố';
$itdung[16]='ố';

$phothong[17]='ũ';
$itdung[17]='ũ';

$phothong[18]='ứ';
$itdung[18]='ứ';

$phothong[19]='ĩ';
$itdung[19]='ĩ';

$phothong[20]='õ';
$itdung[20]='õ';

$phothong[21]='ú';
$itdung[21]='ú';

$phothong[22]='ữ';
$itdung[22]='ữ';

$phothong[23]='ị';
$itdung[23]='ị';

$phothong[24]='ỗ';
$itdung[24]='ỗ';

$phothong[25]='ì';
$itdung[25]='ì';

$phothong[26]='ề';
$itdung[26]='ề';

$phothong[27]='ể';
$itdung[27]='ể';

$phothong[28]='ẩ';
$itdung[28]='ẩ';

$phothong[29]='ớ';
$itdung[29]='ớ';

$phothong[30]='ặ';
$itdung[30]='ặ';

$phothong[31]='ò';
$itdung[31]='ò';

$phothong[32]='ù';
$itdung[32]='ù';

$phothong[33]='ồ';
$itdung[33]='ồ';

$phothong[34]='ợ';
$itdung[34]='ợ';

$phothong[35]='ã';
$itdung[35]='ã';

$phothong[36]='ụ';
$itdung[36]='ụ';

$phothong[37]='ủ';
$itdung[37]='ủ';

$phothong[38]='í';
$itdung[38]='í';

$phothong[39]='ỹ';
$itdung[39]='ỹ';

$phothong[40]='ắ';
$itdung[40]='ắ';

$phothong[41]='ẫ';
$itdung[41]='ẫ';

$phothong[42]='ự';
$itdung[42]='ự';

$phothong[43]='ỉ';
$itdung[43]='ỉ';

$phothong[44]='ỏ';
$itdung[44]='ỏ';

$phothong[45]='ừ';
$itdung[45]='ừ';

$phothong[46]='ỷ';
$itdung[46]='ỷ';

$phothong[47]='ở';
$itdung[47]='ở';

$phothong[48]='ó';
$itdung[48]='ó';

$phothong[49]='é';
$itdung[49]='é';

$phothong[50]='ử';
$itdung[50]='ử';

$phothong[51]='ỵ';
$itdung[51]='ỵ';

$phothong[52]='ẳ';
$itdung[52]='ẳ';

$phothong[53]='ẹ';
$itdung[53]='ẹ';

$phothong[54]='è';
$itdung[54]='è';

$phothong[55]='ổ';
$itdung[55]='ổ';

$phothong[56]='ẽ';
$itdung[56]='ẽ';

for ($d=0;$d<57;$d++) {
    $str = str_replace($itdung[$d], $phothong[$d], $str);
}
return $str;
}

Đoạn mã này sẽ chuyển các ký tự tiếng Việt có dấu (sắc, huyền, hỏi, ngã, nặng) đang được mã hóa ở dạng không phổ thông về dạng phổ thông.

Trong trường hợp bạn muốn làm ngược lại, tức là chuyển từ dạng phổ thông sang không phổ thông thì bạn chỉ việc thay đoạn mã:

$str = str_replace($itdung[$d], $phothong[$d], $str);

bằng đoạn mã:

$str = str_replace($phothong[$d], $itdung[$d], $str);

$str chính là chuỗi tiếng Việt mà chúng ta cần xử lý.

Nếu không thực hiện đồng bộ mã hóa thì chuyện gì xảy ra?

Nó sẽ dẫn đến chuyện hệ thống xem 2 từ có kiểu hình giống nhau (là từ giống nhau trong thực tế) là hai từ khác nhau. Ví dụ:

  • nguyễn (hex: 6e677579e1bb856e) sẽ khác nguyễn (hex: 6e677579c3aacc836e) khi bạn viết lệnh thống kê bằng PHP

Do âm ễ được mã hóa khác nhau trong 2 từ này. Từ ễ thứ nhất / phổ thông được mã hóa trực tiếp bằng mã e1bb85 còn từ thứ hai được mã hóa bằng cách ghép mã hóa của ê (c3aa) và dấu ngã (cc83).

Các mã hex của dấu:

  • Huyền: cc80
  • Sắc: cc81
  • Ngã: cc83
  • Hỏi: cc89
  • Nặng: cca3

Câu lệnh để xuất mã hex trong PHP là bin2hex, ví dụ:

echo bin2hex('ễ'); // sẽ xuất mã hex cho ký tự ễ

Ngay cả việc dùng bộ mã utf8mb4_unicode_ci thay cho các bộ mã khác như utf8_general_ci cũng không giải quyết được vấn đề này khi bạn thống kê bằng PHP. Chẳng hạn lệnh:


    require 'database.php'; // tai database

    $query1a="SELECT * FROM bang_hoten";
    $result=$db->query($query); 
    $ho="nguyễn";
    $dem=0;
    foreach ($result as $value) {
		if ($value['ho'] == $ho) {
			$dem++;
		}
	}
    echo $dem;

Kết quả $dem sẽ chỉ trả về số lượng họ nguyễn là một trong hai số lượng của mã hóa riêng biệt trên (tùy thuộc vào giá trị của biến $ho là gì).

Tuy nhiên việc dùng utf8mb4_unicode_ci vẫn là điều nên làm, việc thống kê trực tiếp bằng câu lệnh SQL sẽ cho kết quả chính xác chứ không giống khi viết lệnh PHP. Ngoài ra bộ mã này còn có nhiều lợi ích khác.

Leave a Comment