10/10/2018, 09:45

PHP MYSQL Unicode & chuyển đổi latin1

Hi all,
Vấn đề Unicode đã và sẽ làm nhiều lập trình viên PHP MySQL đau đầu. Sau đây là 1 bài viết có chút xíu liên quan đến việc chuyển đổi bảng mã latin1 => Unicode.
Ai thấy hữu ích thì phát triển thêm lên nhé:
1. DB Latin 1
Code:
CREATE DATABASE `latindatabase` DEFAULT CHARACTER SET latin1 COLLATE latin1_general_ci;
CREATE TABLE `article` (
`id` INT NOT NULL AUTO_INCREMENT ,
`title` VARCHAR( 255 ) NOT NULL ,
`content` TEXT NOT NULL ,
PRIMARY KEY ( `id` ) 
)
Sau đây là trang code vừa xem danh sách vừa add luôn (thông cảm không có edit vì làm chỉ thêm rắc rối):
config.php
Code:
<?php
$mysql_host="localhost";
$mysql_username="test";
$mysql_password="test";
$mysql_databasename="latindatabase";
?>
dbconnect.php
Code:
<?php
include 'config.php';
$dbp=mysql_connect($mysql_host,$mysql_username,$mysql_password);
mysql_select_db($mysql_databasename,$dbp);
?>
index.php
Code:
<?php
include 'dbconnect.php';
if ($_POST['title'] != "") {
	$sql = "INSERT INTO article(title, content) VALUES ('".$_POST['title']."', '".$_POST['content']."')";
	$result = mysql_query($sql);
}
?>
<html>
<head>
<title>Article View and Add</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<?php
$sql = "SELECT * FROM article";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
	echo "<b>".$row['id']." - ".$row['title']."</b><br>";
	echo $row['content']."<br><br>";
}
?>

<form name="articleadd" method="post" action="">
  <p>Title: 
    <input type="text" name="title">
    </p>
  <p>Content:<br>
    <textarea name="content"></textarea>
    </p>
  <p>
    <label>
    <input type="submit" name="button" id="button" value="Submit">
    </label>
  </p>
</form>
Kết quả view trên Firefox:


Tiếp tục, như trên các bạn đã thấy là hiển thị ngon lành, ghi vào lấy ra đều là Unicode.
Vấn đề là ở chỗ, trong DB thì nó thế này.

Nghĩa là lộn xà lộn xộn (theo nghĩa nào đó) và nhìn không có vẻ gì là Unicode cả.


Sau đây là phần DB hoàn toàn Unicode:
Code:
CREATE DATABASE `unicodedatabase` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE TABLE `article` (
`id` INT NOT NULL AUTO_INCREMENT ,
`title` VARCHAR( 255 ) NOT NULL ,
`content` TEXT NOT NULL ,
PRIMARY KEY ( `id` )
Hệ thống file lần này có đôi chút khác biệt:
config.php
Code:
<?php
$mysql_host="localhost";
$mysql_username="test";
$mysql_password="test";
$mysql_databasename="unicodedatabase";
?>
dbconnect.php
Code:
<?php
include 'config.php';
$dbp=mysql_connect($mysql_host,$mysql_username,$mysql_password);
mysql_select_db($mysql_databasename,$dbp);
?>
index.php
Code:
<?php
include 'dbconnect.php';
mysql_query("SET NAMES 'utf8'");
if ($_POST['title'] != "") {
	$sql = "INSERT INTO article(title, content) VALUES ('".$_POST['title']."', '".$_POST['content']."')";
	$result = mysql_query($sql);
}
?>
<html>
<head>
<title>Article View and Add</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<?php
$sql = "SELECT * FROM article";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
	echo "<b>".$row['id']." - ".$row['title']."</b><br>";
	echo $row['content']."<br><br>";
}
?>

<form name="articleadd" method="post" action="">
  <p>Title: 
    <input type="text" name="title">
    </p>
  <p>Content:<br>
    <textarea name="content"></textarea>
    </p>
  <p>
    <label>
    <input type="submit" name="button" id="button" value="Submit">
    </label>
  </p>
</form>
Hiển thị trên FF:


Và trong DB = PHPMYADMIN:


Giờ mới là đoạn hay nhất, cho phép chuyển từ latin1 sang Unicode:

config.php
Code:
<?php
$mysql_host="localhost";
$mysql_username="test";
$mysql_password="test";
$mysql_databasename="unicodedatabase";
?>
dbconnect.php
Code:
<?php
include 'config.php';
$dbp=mysql_connect($mysql_host,$mysql_username,$mysql_password);
mysql_select_db($mysql_databasename,$dbp);
?>
config2.php
Code:
<?php
$mysql_host="localhost";
$mysql_username="test";
$mysql_password="test";
$mysql_databasename="latindatabase";
?>
dbconnect2.php
Code:
<?php
include 'config2.php';
$dbp=mysql_connect($mysql_host,$mysql_username,$mysql_password);
mysql_select_db($mysql_databasename,$dbp);
?>
convert.php
Code:
<html>
<head>
<title>Article Convert</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<?php
include 'dbconnect2.php';
//First select all from one database
$sql = "SELECT * FROM article";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
	$rows[] = $row;
}

//Then insert to the other
include 'dbconnect.php';
mysql_query("SET NAMES 'utf8'");
foreach($rows as $row) {
	$sql = "INSERT INTO article(title, content) VALUES ('".$row['title']."', '".$row['content']."')";
	$result = mysql_query($sql);
}
?>
Convert finished!
Kết quả sau khi convert:

Xong.
chary1112004 viết 11:52 ngày 10/10/2018
Cảm ơn bạn rất nhiều! Mặc dù chưa thử nhưng mình nghĩ đây là bài viết đầy kinh nghiệm !
dbvn88 viết 11:52 ngày 10/10/2018
Cảm ơn anh Tiến 1 bài viết rất hay
Vô Thin viết 11:47 ngày 10/10/2018
À, nhờ bác Tiến gỡ rối giúp vụ này luôn. Bác vào diễn đàn Khoan Cắt Bê Tông của bọn này tại: http://khoancatbetong.com/forum/

Thoạt nhìn. Forum rất bình thường. Các chuyên mục hiển thị bình thường. Nào, thử vào một chuyên mục. Cái gì thế này:



Nhưng click thử vào một bài viết thì đọc ngon lành.

Không có chỉnh gì ở DB cả. Vấn đề là DB ở host cũ đã là collation=utf8_unicode_ci và tất cả các table, các trường bên trong đều có collation=utf8_unicode_ci, hiển thị tiếng Việt bình thường, đọc tốt trong phpMyAdmin. Nhưng rồi khi backup về bằng phpMyAdmin, bên cung cấp host gõ lệnh trên console,... thì đều về được file .sql ngon lành, mở thử bằng một trình soạn thảo text hỗ trợ Unicode thì đọc được tiếng Việt tốt. Nhưng khi qua nhà cung cấp host cũng collation=utf8_unicode_ci với phpMyAdmin và import vào thì nó ra hiện tượng như trên.

Hẳn là bác Tiến từng nghịch phpBB 3.0 nên đang có DB của nó và có thể xem xét các table với phpMyAdmin và tìm giúp xem nó bị lộn xộn kiểu gì mà như thế.

Cám ơn bác rất nhiều!
chary1112004 viết 11:51 ngày 10/10/2018
Mình đang connect tới Sql 2000 nhưng khi dùng câu lệnh mssql_query("SET NAMES 'utf8'"); (Mình có thay đổi từ mysql_query thành mssql_query) nhưng nó thông báo lỗi như sau:
Warning: mssql_query() [function.mssql-query]: message: 'NAMES' is not a recognized SET statement. (severity 15) in \php\Car\Connect\Connect.php on line 12

Mình đang cần debug vấn đề này. Mong bạn chỉ giúp. Cám ơn bạn nhiều!
Vô Thin viết 11:50 ngày 10/10/2018
Được gửi bởi chary1112004
Mình đang connect tới Sql 2000 nhưng khi dùng câu lệnh mssql_query("SET NAMES 'utf8'"); (Mình có thay đổi từ mysql_query thành mssql_query) nhưng nó thông báo lỗi như sau:
Warning: mssql_query() [function.mssql-query]: message: 'NAMES' is not a recognized SET statement. (severity 15) in \php\Car\Connect\Connect.php on line 12

Mình đang cần debug vấn đề này. Mong bạn chỉ giúp. Cám ơn bạn nhiều!
Có lẽ bạn cần phải tra cứu lệnh SQL của MS SQL Server. Bởi vì tuy cùng dùng ngôn ngữ SQL nhưng MS SQL Server và MySQL có nhiều điểm khác biệt.

Lỗi bạn có lẽ là do câu lệnh: mssql_query("SET NAMES 'utf8'"); là một câu lệnh không hợp lệ, SQL Server không chấp nhận vì nó không hiểu SET NAMES là gì cả.
tiendx2002 viết 11:49 ngày 10/10/2018
Được gửi bởi superthin
À, nhờ bác Tiến gỡ rối giúp vụ này luôn. Bác vào diễn đàn Khoan Cắt Bê Tông của bọn này tại: http://khoancatbetong.com/forum/

Thoạt nhìn. Forum rất bình thường. Các chuyên mục hiển thị bình thường. Nào, thử vào một chuyên mục. Cái gì thế này:



Nhưng click thử vào một bài viết thì đọc ngon lành.

Không có chỉnh gì ở DB cả. Vấn đề là DB ở host cũ đã là collation=utf8_unicode_ci và tất cả các table, các trường bên trong đều có collation=utf8_unicode_ci, hiển thị tiếng Việt bình thường, đọc tốt trong phpMyAdmin. Nhưng rồi khi backup về bằng phpMyAdmin, bên cung cấp host gõ lệnh trên console,... thì đều về được file .sql ngon lành, mở thử bằng một trình soạn thảo text hỗ trợ Unicode thì đọc được tiếng Việt tốt. Nhưng khi qua nhà cung cấp host cũng collation=utf8_unicode_ci với phpMyAdmin và import vào thì nó ra hiện tượng như trên.

Hẳn là bác Tiến từng nghịch phpBB 3.0 nên đang có DB của nó và có thể xem xét các table với phpMyAdmin và tìm giúp xem nó bị lộn xộn kiểu gì mà như thế.

Cám ơn bác rất nhiều!
Chào bác superthin,
Theo em thì bác có thể xài thằng bigdump xem vì thằng này xem ra tốt hơn là phpmyadmin khi import. Chú ý chỗ encode ở line 67:
PHP Code:
$db_connection_charset 'utf8'
Được gửi bởi chary1112004
Mình đang connect tới Sql 2000 nhưng khi dùng câu lệnh mssql_query("SET NAMES 'utf8'"); (Mình có thay đổi từ mysql_query thành mssql_query) nhưng nó thông báo lỗi như sau:
Warning: mssql_query() [function.mssql-query]: message: 'NAMES' is not a recognized SET statement. (severity 15) in \php\Car\Connect\Connect.php on line 12

Mình đang cần debug vấn đề này. Mong bạn chỉ giúp. Cám ơn bạn nhiều!
Đúng như ở trên superthin có để ý đó, là bạn dùng MSSQL thì phải xem các câu lệnh của nó. Bên mình chỉ dùng MySQL vì tính thông dụng và miễn phí của nó, nên cũng không đọc gì về MSSQL cả.
Đành giới thiệu bạn qua ông bác Google thôi .
Thân ái.
herofit viết 11:48 ngày 10/10/2018
Được gửi bởi superthin
À, nhờ bác Tiến gỡ rối giúp vụ này luôn. Bác vào diễn đàn Khoan Cắt Bê Tông của bọn này tại: http://khoancatbetong.com/forum/

Thoạt nhìn. Forum rất bình thường. Các chuyên mục hiển thị bình thường. Nào, thử vào một chuyên mục. Cái gì thế này:



Nhưng click thử vào một bài viết thì đọc ngon lành.

Không có chỉnh gì ở DB cả. Vấn đề là DB ở host cũ đã là collation=utf8_unicode_ci và tất cả các table, các trường bên trong đều có collation=utf8_unicode_ci, hiển thị tiếng Việt bình thường, đọc tốt trong phpMyAdmin. Nhưng rồi khi backup về bằng phpMyAdmin, bên cung cấp host gõ lệnh trên console,... thì đều về được file .sql ngon lành, mở thử bằng một trình soạn thảo text hỗ trợ Unicode thì đọc được tiếng Việt tốt. Nhưng khi qua nhà cung cấp host cũng collation=utf8_unicode_ci với phpMyAdmin và import vào thì nó ra hiện tượng như trên.

Hẳn là bác Tiến từng nghịch phpBB 3.0 nên đang có DB của nó và có thể xem xét các table với phpMyAdmin và tìm giúp xem nó bị lộn xộn kiểu gì mà như thế.

Cám ơn bác rất nhiều!
lỗi này thường sẩy ra bạn export và import mysql khác version, cũng có 1 lần mình bị giống bạn do dùng version phpbb3 cũ bạn thử update lên version mới thử xem
Vô Thin viết 11:57 ngày 10/10/2018
Có lẽ anh em ở đây nên xúm nhau vào mổ xẻ cho nó ra ngô khoai vấn đề giun dế này luôn đi. Tui thấy bức xúc cái chuyện này quá, mà đi dạo lên khắp diễn đàn thì mỗi nơi mỗi phách và cứ "có dịp" backup, restore, chuyển nhà cung cấp hosting, nâng cấp các diễn đàn, cms,... và các ứng dụng web khác liên quan đến PHP, MySQL là y như rằng phải... ngồi mà cầu nguyện Chúa và hy vọng rằng sau khi thực hiện xong thì mọi thứ suôn sẻ. Có suôn sẻ? Chỉ có 50% cơ hội cho chúng ta.

Hôm nay tức khí cái vụ giun giun dế dế như trên quá. Thế là mình phải ngồi cài máy Linux của mình gần giống y như trên host về các phần mềm cài đặt web server: nói chung là Apache giống hệt phiên bản trên host, MySQL cũng cùng phiên bản, phpMyAdmin cũng giống hệt, thậm chí cái đặt forum giống hệt, các thông số về path,... gần như là một bản sao của hosting, chỉ có điều máy RAM ít hơn, bộ xử lý kém hơn mà thôi. Và công cuộc khám phá bắt đầu. Vì mình còn rất amateur nên cần các bạn ở đây cùng tham gia phân tích giúp. Chúng ta cùng nhau giải quyết triệt để mọi tình huống để sau này nhỡ bị giun dế biết cách mà convert để trở lại bình thường, không thì có khi vài Gigabyte dữ liệu đổ sông biển cả thì... toi cơm.

Theo các diễn đàn về MySQL trên thế giới thì lỗi font chữ không phải tiếng Anh là... như cơm bữa, và bọn webmaster nước ngoài cũng cay cú không kém anh em chúng ta. Nhất là các thứ tiếng như Nhật Bản, Trung Quốc, Ả Rập, Thổ Nhĩ Kỳ, Thái Lan, một vài nước Đông Âu,... là kiểu gì thì cũng có ngày ra mì gói bẻ vụn như hình ảnh diễn đàn mình minh họa trên.

Mình thấy rằng vấn đề là rối rắm, trừ khi ta thuê VPS hoặc Dedicated hosting thì mới giải quyết triệt để vấn đề về charset, collate, encoding,... mà thôi. Bởi vì các host cài đặt có những thông số hệ thống của MySQL Server, MySQL Client (là mấy cái .dll hoặc .so của PHP ấy) mà ở phía người thuê host dạng shared host là chịu thua, không thể chỉnh sửa được (hoặc có cách nhưng mình chưa biết).

Chúng ta nên đi theo giải pháp là giải quyết cho shared hosting, vì cái này nhiều người thuê. Làm thế nào để chúng ta tổng kết được: Nếu trên host là A thì ta có cách B, nếu thông số trên host là X, thì ta có cách là Y,... những cách này là tương ứng và cố định để nhỡ đụng thì ta so vào và cứ thế mà làm, đỡ mất thời giờ ngồi mà nghiền ngẫm / mò mẫm. Làm thế nào đó để cuối cùng là toàn bộ tiếng Việt của ta trong database phải hiển thị tốt trên trang web của ta, không được ra dấu ?, ô vuông hoặc giun dế đọc không được.

Minh họa sự rối rắm như sau:

Vào phpMyAdmin, ta chọn bất kỳ một database nào đã tạo. Và gõ lệnh: SHOW VARIABLES; thì thấy nhiều thứ rất là thú vị đây, mình lượt bớt, chỉ lấy đoạn liên quan đến charset, collate:



Phải chi nó là utf8 hết thì có lẽ là ta đỡ vất vả rồi. Đàng này lại nảy nòi ra thêm 2 cái (mình khoanh đỏ) mới làm đau đầu nhức óc làm sao. Mà cái này thì chỉ có ta thuê host riêng thì may ra có thể compile lại MySQL từ nguồn hoặc sửa file cấu hình để cho nó thành utf8 luôn.

Cho nên, không phải lúc nào ta cũng cứ chèn cái dòng mysql_query("SET NAME 'utf8'"); trước khi query để lấy dữ liệu / thêm dữ liệu vào database và chắc mẩm rằng nó sẽ hiển thị tốt tiếng Việt. Rất nhiều khi là khi vào phpMyAdmin thử browse các trường text tiếng Việt ra xem, ta không thể đọc được, nó dạng giun dế, dù ta có chỉnh charset, collate kiểu gì ở phpMyAdmin cũng thua. Nhưng ở kết quả đầu ra từ script của ta thì tiếng Việt rất ngon lành.

Ngược lại, cũng có trường hợp, nhìn trong phpMyAdmin tiếng Việt rất tốt, nhưng khi ra trình duyệt chạy script của ta thì ra ô vuông, dấu hỏi hoặc giun dế. Dù ta chắc rằng trình duyệt đã encoding utf-8, thẻ meta trong HTML cũng charset là utf-8.

Như vậy, cả 2 trường hợp trên, ta chớ có nghịch ngợm bằng cách dùng phpMyAdmin ra để chỉnh sửa dữ liệu, mà luôn phải dùng script do ta viết để "nghịch" database cho an toàn. Nếu dùng phpMyAdmin phải hết sức thận trọng, nên input dữ liệu vào ở dạng mã Decimal hoặc HEX mà trong Unikey có cung cấp, hay dùng trình thiết kế web FrontPage gõ tiếng Việt và lấy nó khi xem code HTML.

Khi mà ở phpMyAdmin đọc được tiếng Việt tốt, ở script ta xuất ra cũng tiếng Việt tốt. Lúc này dĩ nhiên là ta có thể dùng phpMyAdmin như kiểu nhập liệu trong Access hay Excel để làm nhanh một số thao tác mà ta chưa kịp viết code để nhập liệu cho ứng dụng của ta.

Đó là chưa kể khi backup về bằng gõ lệnh trên command line của MySQL thì cho kết quả khác, dùng phpMyAdmin cho kết quả khác, dùng các công cụ khác ở phần mềm do nhà cung cấp host trang bị như Webmin, CPanel, Plesk, DirectAdmin thì nó ở dạng gì ta cũng mù mờ nốt. Thuê host mới lại phải dùng thứ khác => rối beng => kết quả là tiếng Việt có dấu sẽ trở nên không đọc được.

Bây giờ, anh em chúng ta cùng nhau tìm cách dump dữ liệu ra bằng script do ta viết, dù ở tình huống nào trên server ta cũng phải detect nó để biết nó đang charset là gì, collation là gì và chuyển thành một file .sql và script của ta sẽ làm việc restore vào host nào đó bất kỳ theo sự detect của nó mà không phụ thuộc vào phpMyAdmin, cũng không bigdump. Chỉ đến mức này thì chúng ta mới hoàn thành vấn đề đau đầu bấy nay.

Cuối cùng, rất cám ơn bác Tiến đã giới thiệu bigdump rất mạnh mẽ, dùng tốt nhưng vấn đề giun dế của em vẫn còn nằm trêu ngươi đó. Nhờ bác tham gia vụ này để chúng ta tìm ra qui luật của mấy cái sự lộn xộn kia.
tiendx2002 viết 11:50 ngày 10/10/2018
Được gửi bởi superthin
rất cám ơn bác Tiến đã giới thiệu bigdump rất mạnh mẽ, dùng tốt nhưng vấn đề giun dế của em vẫn còn nằm trêu ngươi đó. Nhờ bác tham gia vụ này để chúng ta tìm ra qui luật của mấy cái sự lộn xộn kia.
Chắc chắn là phải cố gắng rồi. superthin đã nhờ thì không thể không cố được .
Qua phân tích sơ bộ thì của bác chỉ có lỗi ở http://khoancatbetong.com/forum/viewforum.php?f=3
Những trang có show thread title nói chung bị lỗi.
Các phần như language và thread content đều ổn.
Khả năng cao nhất là bản DB này có lỗi ở bảng thread.
Investigating để coi lỗi gì.
Còn về vấn đề mà bác đề cập tới liên quan đến 1 cái tool như vậy chắc chắc là hay rồi, nhưng hiện nay thì em chưa làm được, và welcome mọi người sử dụng ý tưởng của bác superthin và những cái đã public biết đâu lại kiếm được $ ấy chứ , thêm kiến thức thì khỏi phải nói.
Thân ái.
Bài liên quan
0