Hôm nay thử cài đặt CakePHP 3.6 để kiểm tra các chức năng mới thì phát hiện từ phiên bản 3.6, CakePHP sử dụng setting 'encoding' => 'utf8mb4'
mặc định cho database MySQL, thay cho 'encoding' => 'utf8'
ở các phiên bản trước.
Chính vì setting mặc định này mà khi kết nối thử tới database MySQL thì bị lỗi sau:
2019, "Can't initialize character set utf8mb4 (path: /usr/share/mysql/charsets/)"
Khi tìm hiểu về lỗi này thì mình mới phát hiện ra trước giờ mình có 2 ngộ nhận về PHP và MySQL (có thể còn nhiều ngộ nhận khác nữa mà mình chưa biết). Vậy mới biết giữa bể học mênh mông này, kiến thức của mình chỉ là có hạn.
2 ngộ nhận:
- Ngộ nhận 1:
trong MySQL, khi muốn lưu các ký tự encodeutf8
, chỉ việc sử dụng encodingutf8
(cụ thể làutf8-general-ci
) - Ngộ nhận 2:
trong PHP, khi muốn kết nối với MySQL, chỉ việc cài đặt thư việnphp-mysql
Về ngộ nhận 1
Nói một cách ngắn gọn, trên MySQL utf8mb4
mới thực sự là utf8, còn utf8
trên MySQL chỉ là bộ encoding gần đúng của utf8 mà thôi.
Như đã biết thì chuẩn utf8 sử dụng bộ mã khả biến (1~4 byte) để mã hoá cho các ký tự. Tuy nhiên trên MySQL, bộ encoding utf8
chỉ sử dụng tối đa 3 byte để mã hóa ký tự. Từ phiên bản MySQL5.5 (hình như) mới xuất hiện bộ encoding mới utf8mb4
sử dụng tối đa 4 byte, đúng với utf8 chuẩn.
Do chỉ dùng tối đa 3 byte nên khi sử dụng utf8
trên MySQL để lưu những ký tự đặc biệt (nằm ngoài bảng Basic Multilingual Plane, ví dụ như các emoji) thì sẽ xảy ra lỗi.
Muốn làm việc chính xác với utf8 trên MySQL thì cần sử dụng encoding utf8mb4
. Và cũng có rất nhiều ý kiến khuyên nên sử dụng utf8mb4
thay cho utf8
trên MySQL (đây là 1 ví dụ).
Về ngộ nhận 2:
Theo như tài liệu của PHP cũng như nhiều nguồn khác, thì nên sử dụng library php-mysqlnd
thay cho php-mysql
. Lý do là thư viện này được hỗ trợ chính thức bởi PHP và có nhiều chức năng hơn so với thư việc cũ (cụ thể chức năng nào thì trong tài liệu trên đã có nói).
Và cũng chính vì sử dụng library cũ php-mysql
mà xuất hiện lỗi liên quan đến encoding utf8mb4
như ở trên (mặc dù mình đã set encoding cho database là utf8mb4
cho khớp với setting mặc định của CakePHP 3.6). Sau khi chuyển sang cài library mới php-mysqlnd
thì hết lỗi trên.