Hướng dẫn dùng char name trong PHP

Việc xử lý chuỗi trong lập trình PHP rất quan trọng vì dữ liệu để hiển thị trên trang web đa phần là ở dạng chuỗi. Vì thế việc hiểu và nắm vững kiến thức trong xử lý chuỗi sẽ giúp bạn tối ưu hóa hiệu suất của website và đẩy nhanh tiến độ thiết kế website. Dưới đây là một số hàm và toán tử xử lý chuỗi trong PHP:

Nội dung chính

  • PHP và mã hóa UTF-8
  • Ở header:
  • Trong file XML:
  • Trong HTML:
  • Chỉ định UTF-8 trong hàm hmlspecialchars:
  • Khi kết nối với MySQL:
  • Sử dụng hàm xử lý chuỗi tương thích với UTF-8:
  • MySQL với mã hóa UTF-8
  • Thay đổi trong file config my.ini:
  • Chuyển đổi dữ liệu sử dụng mã hóa latin1 sang UTF-8
  • Lời kết

Toán tử nối chuỗi: Để nối 2 chuỗi chúng ta sử dụng toán tử [.] 

Ví dụ: echo "abc"." "."def";

Các hàm xử lý chuỗi cơ bản

Hàm strlen[string]: được sử dụng để tính chiều dài của chuỗi

Ví dụ:

//kết quả in ra:12

Hàm str_word_count[string $string [, int $format = 0 [, string $charlist ]]] : đếm tổng số từ có trong chuỗi

  • string: chỉ định chuỗi để kiểm tra
  • format: chỉ định kiểu giá trị trả về của hàm str_word_count[]. Các giá trị này có thể là:
    • 0 - Mặc định - trả về số lượng từ đếm được
    • 1 - Trả về một mảng chứa các từ trong chuỗi
    • 2 - Trả về một mảng với key là vị trí của từ trong chuỗi và value là từ trong chuỗi
  • charlist: chỉ định các ký tự đặc biệt sẽ được xem như một từ trong chuỗi 

Ví dụ:

//kết quả in ra: Array [ [0] => Hello [1] => world ]

Hàm strtoupper[string]: đổi chữ thường thành hoa.
Hàm strtolower[string]: đổi chữ hoa thành thường.
Hàm ucfirst[string]: đổi chữ in ký tự đầu tiên của chuỗi.
Hàm ucwords[string]: đổi chữ in ký tự đầu tiên của mỗi từ trong chuỗi.
Hàm trim[$string, $character]; Xóa ký tự $character nằm ở đầu và cuối chuỗi $str, nếu ta không nhập $character thì mặc định nó hiểu là xóa khoảng trắng.
Hàm ltrim[$string, $character]: Tương tự như trim nhưng chỉ xóa bên trái
Hàm rtrim[$string, $character]: Tương tự như trim nhưng chỉ xóa bên phải

Hàm tìm kiếm và thay thế chuỗi

Hàm substr[ string $string , int $start [, int $length ] ]: cắt ra một phần của chuỗi từ vị trí start một đoạn được chỉ định bằng tham số length

  • string: chuỗi nhập vào đẻ cắt ra chuỗi con
  • start: nếu start là một số dương, chuỗi được trả về sẽ bắt đầu từ vị trí start [ký tự đầu tiên của chuỗi được tính là 0]. Nếu start là một số âm chuỗi con trả về sẽ được cắt từ vị trí start tính từ cuối chuỗi.
  • length: độ dài của chuỗi trả về. Mặc định length được tính đến cuối chuỗi
    • length>0: độ dài của chuỗi trả về được tính từ đầu chuỗi
    • length<0: độ dài của chuỗi trả về được tính từ cuối chuỗi

 Ví dụ:

"; echo substr["Hello world",1]."
"; echo substr["Hello world",3]."
"; echo substr["Hello world",7]."
"; echo "
"; // Negative numbers: echo substr["Hello world",-1]."
"; echo substr["Hello world",-10]."
"; echo substr["Hello world",-8]."
"; echo substr["Hello world",-4]."
"; ?>

 Kết quả trả về:

d
ello world
lo world
orld

d
ello world
lo world
orld

Hàm explode[$delimiter, $string]: chuyển một chuỗi string thành một mảng các phần tử với ký tự tách mảng là delimiter.

Ví dụ:

$str = 'programming and digital marketing training'; // sử dụng dấu cách làm kí tự tách các phần từ từ chuỗi đưa vào mảng
var_dump[explode[' ', $str]]; /*Kết quả array 0 => 'programming', 1 => 'and', 2 => 'digital' , 3 => 'marketing', 4 => 'training'

Hàm implode[$delimiter, $piecesarray]: ngược với hàm explode, nó chuyển một mảng $piecesarray thành chuỗi và mỗi phần tử trong mảng được nối với nhau bởi chuỗi $delimiter

Ví dụ:

Hàm strstr[ $string, $needle]: Tách một chuỗi bắt đầu từ $needle cho đến hết chuỗi.

Ví dụ:

Hàm strpos[$string, $needle]: Tìm vị trí của chuỗi $needle trong chuỗi $string, kết quả trả về vị trí đầu tiên của $needle nếu tìm thấy và false nếu không tìm thấy.

Ví dụ:

$mystring = 'abc'; $findme = 'b'; $pos = strpos[$mystring, $findme]; echo $pos; //kết quả: 1

Nội dung chính

  • PHP và mã hóa UTF-8
  • Ở header:
  • Trong file XML:
  • Trong HTML:
  • Chỉ định UTF-8 trong hàm hmlspecialchars:
  • Khi kết nối với MySQL:
  • Sử dụng hàm xử lý chuỗi tương thích với UTF-8:
  • MySQL với mã hóa UTF-8
  • Thay đổi trong file config my.ini:
  • Chuyển đổi dữ liệu sử dụng mã hóa latin1 sang UTF-8
  • Lời kết

Đã đăng vào thg 12 2, 2017 6:45 CH 7 phút đọc

Đối với một lập trình viên PHP hay MySQL, mọi thứ có vẻ khá dễ dàng và thoải mái khi làm việc với dữ liệu chỉ gồm các ký tự tiếng Anh. Cho đến khi bạn vướng vào sự rắc rối của mã hóa UTF-8 trong xử lý ngôn ngữ không phải tiếng Anh. Nói sơ lược về mã hóa UTF-8 thì đây là một kiểu mã hóa ký tự của tập ký tự Unicode. Nó được thiết kế để tương thích ngược với mã hóa ASCII và tránh những nhược điểm của UTF-16 và UTF-32. UTF-8 trở thành kiểu mã hóa phổ biến và chiếm ưu thế khi hơn một nửa số trang web hiện tại sử dụng kiểu mã hóa này. Trong bài viết này, sẽ có 3 hướng dẫn chính được trình bày để có thể sử dụng mã hóa UTF-8 trong PHP và MySQL:

  • Thay đổi trong file config php.ini và PHP code.
  • Thay đổi trong file config my.ini và những vấn đề liên quan khác đến MySQL.
  • Thay đổi dữ liệu trong CSDL MySQL sử dụng mã hóa latin1 thành mã hóa UTF-8.

PHP và mã hóa UTF-8

Để sử dụng UTF-8 là kiểu mã hóa ký tự mặc định, thay đổi ở file config php.ini như sau: default_charset = "utf-8"; Thay đổi trong PHP code:

Ở header:

header['Content-Type: text/html; charset=utf-8'];

Trong file XML:

Tuy nhiên, không phải tất cả ký tự UTF-8 đều được chấp nhận ở trong XML, vì vậy cần loại bỏ những ký tự này. Một hàm hữu dụng sau đây có thể giải quyết vấn đề trên:

function utf8_for_xml[$string] { return preg_replace['/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $string]; }

Trong HTML:

  • HTML content:
  • HTML form:

Chỉ định UTF-8 trong hàm hmlspecialchars:

htmlspecialchars[$str, ENT_NOQUOTES, "UTF-8"]

Khi kết nối với MySQL:

Sử dụng hàm mysql_set_charset:

$link = mysql_connect['localhost', 'user', 'password']; mysql_set_charset['utf8', $link];

Từ PHP 5.5.0, hàm mysql_set_charset được thay thế bởi mysql::set_charset

$mysqli = new mysqli["localhost", "my_user", "my_password", "test"]; /* check connection */ if [mysqli_connect_errno[]] { printf["Connect failed: %s\n", mysqli_connect_error[]]; exit[]; } /* change character set to utf8 */ if [!$mysqli->set_charset["utf8"]] { printf["Error loading character set utf8: %s\n", $mysqli->error]; } else { printf["Current character set: %s\n", $mysqli->character_set_name[]]; } $mysqli->close[];

Sử dụng hàm xử lý chuỗi tương thích với UTF-8:

Có nhiều hàm sẽ lỗi hoặc xử lý sai khi một ký tự cần nhiều hơn 1 byte [như UTF-8]. Ví dụ hàm strlen sẽ trả về số lượng byte chứ không phải số lượng ký tự. Để giải quyết việc này có 2 tùy chọn:

  1. Sử dụng các hàm iconv [ví dụ: `iconv_strlen,…]. Dù vậy, bản thân chuỗi ký tự vẫn cần phải đảm bảo được mã hóa đúng.
  2. Extension mbstring: extension cung cấp một tập đầy đủ các hàm cho việc xử lý mã hóa sử dụng nhiều byte [multibyte]

MySQL với mã hóa UTF-8

Thay đổi trong file config my.ini:

[client] default-character-set=UTF-8 [mysql] default-character-set=UTF-8 [mysqld] character-set-client-handshake = false #force encoding to uft8 character-set-server=UTF-8 collation-server=UTF-8_general_ci [mysqld_safe] default-character-set=UTF-8
  • MySQL UTF-8 thực sự chỉ là một phần của tập ký tự UTF-8 khi chỉ sử dụng tối đa 3 bytes trong khi mã hóa UTF-8 yêu cầu 4 bytes. Do đó, một số ký tự không được hỗ trợ trong MySQL UTF-8. Kể từ MySQL 5.5.3, điều này có thể được giải quyết với tập ký tự utf8mb4.
  • Trong trường hợp không cài đặt mã hóa khi kết nối với MySQL, thì sau khi kết nối xong, có thể sử dụng lệnh/truy vấn sau: set names UTF-8;
  • Khi xác định kích cỡ của các trường kiểu varchar, đừng quên UTF-8 yêu cầu 4 bytes trên mỗi ký tự.

Chuyển đổi dữ liệu sử dụng mã hóa latin1 sang UTF-8

  1. Thiết lập cài đặt ở file config my.ini như hướng dẫn thứ 2.
  2. Thực hiện câu lệnh sau: ALTER SCHEMAyour-db-nameDEFAULT CHARACTER SET UTF-8;
  3. Xác nhận mọi thứ đã được cài đặt về UTF-8 mysql> show variables like 'char%';
  4. Tạo file dump cho việc chuyển đổi: mysqldump -u USERNAME -pDB_PASSWORD --opt --skip-set-charset --default-character-set=latin1 --skip-extended-insert DATABASENAME --tables TABLENAME > DUMP_FILE_TABLE.sql
  5. Thay thế charset trong file dump từ latin1 sang UTF-8 Ví dụ sử dụng Perl: perl -i -pe 's/DEFAULT CHARSET=latin1/DEFAULT CHARSET=UTF-8/' DUMP_FILE_TABLE.sql Đối với người dùng Windows: Việc chuyển đổi có thể thực hiện bằng WordPad sử dụng chức năng find-and-replace.
  6. Kể từ giờ, việc thay đổi sẽ được thực hiện trên CSDL nên đảm bảo backup dữ liệu trước khi thực hiện mysql> source "DUMP_FILE_TABLE.sql";
  7. Tìm kiếm những bản ghi có thể bị chuyển đổi sai và sửa chúng [ví dụ những ký tự được mã hóa 2 lần]. Vì những ký tự không phải ASCII là multi-byte [sử dụng nhiều hơn 1 byte/ký tự] nên có thể tìm chúng bằng cách so sánh số byte và số lượng ký tự.
  • Kiểm tra có ký tự multi-byte hay không [nếu truy vấn sau trả về 0 thì không có ký tự multi-byte và có thể bỏ qua các bước tiếp theo] mysql> select count[*] from MY_TABLE where LENGTH[MY_FIELD] != CHAR_LENGTH[MY_FIELD];
  • Copy những hàng có ký tự multi-byte sang bảng tạm:
create table temptable [ select * from MY_TABLE where LENGTH[MY_FIELD] != CHAR_LENGTH[MY_FIELD]];
  • Chuyển đổi ký tự bị mã hóa UTF-8 2 lần về dạng UTF-8 chuẩn. Vì MySQL đã tự động chuyển đổi dữ liệu sang UTF-8 một lần nữa trên dữ liệu UTF-8 nên cần một “thủ thuật” nhỏ để tránh việc chuyển đổi này. Đầu tiên, chuyển đổi kiểu mã hóa về latin1, do đó mã hóa 2 lần sẽ bị loại bỏ : alter table temptable modify temptable.ArtistName varchar[128] character set latin1; Lưu ý: Cần đặt đúng kiểu dữ liệu cũ. Như ở ví dụ trên là vachar[128] Vấn đề bây giờ là nếu cài đặt cột hiện tại về mã hóa UTF-8, MySQL sẽ chuyển đổi từ latin1 về UTF-8. Để tránh việc này, chúng ta thay đổi kiểu dữ liệu của cột về blob rồi sau đó mới cài đặt UTF-8. Điều này lợi dụng từ việc MySQL không chuyển đổi kiểu mã hóa của một blob.
alter table temptable modify temptable.ArtistName blob; alter table temptable modify temptable.ArtistName varchar[128] character set UTF-8;
  • Loại bỏ hàng chỉ có ký tự single-byte [sử dụng một byte] ra khỏi bảng tạm: delete from temptable where LENGTH[MY_FIELD] = CHAR_LENGTH[MY_FIELD];
  • Thay thế dữ liệu vào bảng chính replace into MY_TABLE [select * from temptable];
  1. Kiểm tra dữ liệu còn lại, nếu cần thì thực hiện lại từ bước 7.

Lời kết

Mã hóa dữ liệu đòi hỏi sự cẩn trọng và tỉ mỉ. Nếu hiểu rõ về nó, lập trình viên có thể tiết kiệm một khoảng thời gian và công sức đáng kể khi đối mặt với những vấn đề về dữ liệu. Bài viết này như một lần nữa khẳng định tầm quan trọng của việc cân nhắc khi định nghĩa charset trong dự án cũng như môi trường phát triển ngay từ ban đầu.

Referrence: //www.toptal.com/php/a-utf-8-primer-for-php-and-mysql

All rights reserved