Một cái gì đó trong mã của bạn không xử lý chuỗi dưới dạng UTF8. Nó có thể là PHP / HTML của bạn, nó có thể nằm trong kết nối của bạn với DB hoặc có thể là chính DB - mọi thứ phải được đặt thành UTF8 một cách nhất quán và nếu bất kỳ điều gì không phải, chuỗi sẽ bị cắt ngắn chính xác như bạn xem khi đi qua ranh giới UTF8 / không phải UTF8.
Tôi sẽ cho rằng DB của bạn tuân thủ UTF8 - điều đó dễ dàng nhất để kiểm tra. Lưu ý rằng đối chiếu có thể được đặt ở cấp máy chủ, cấp cơ sở dữ liệu, cấp bảng và cấp cột trong bảng. Việc đặt đối chiếu UTF8 trên cột sẽ ghi đè lên bất kỳ thứ gì khác để lưu trữ, nhưng những thứ khác sẽ vẫn hoạt động khi nói chuyện với DB nếu chúng cũng không phải là UTF8. Nếu bạn không chắc chắn, hãy đặt kết nối thành UTF8 một cách rõ ràng sau khi bạn mở nó:
$dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
Bây giờ DB &kết nối của bạn là UTF8, hãy đảm bảo rằng trang web của bạn cũng vậy. Một lần nữa, điều này có thể được đặt ở nhiều nơi (.htaccess, php.ini). Nếu bạn không chắc chắn / không có quyền truy cập, chỉ cần ghi đè bất kỳ thứ gì PHP đang chọn làm mặc định ở đầu trang của bạn:
<?php ini_set('default_charset', 'UTF-8'); ?>
Lưu ý rằng bạn muốn điều trên ngay khi bắt đầu, trước khi bất kỳ văn bản nào được xuất ra từ trang của bạn. Khi văn bản được xuất, có khả năng là quá muộn để thử và chỉ định một kiểu mã hóa - bạn có thể đã bị khóa vào bất kỳ thứ gì được mặc định trên máy chủ của mình. Sau đó, tôi cũng lặp lại điều này trong tiêu đề của mình (có thể quá mức cần thiết):
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
</head>
Và tôi ghi đè nó trên các biểu mẫu mà tôi cũng đang lấy dữ liệu:
<FORM NAME="utf8-test" METHOD="POST" ACTION="utf8-test.php" enctype="multipart/form-data" accept-charset="UTF-8">"
Thành thật mà nói, nếu bạn đã đặt mã hóa ở trên cùng, tôi hiểu rằng các ghi đè khác là không bắt buộc - nhưng tôi vẫn giữ chúng, vì nó cũng không phá vỡ bất cứ điều gì và tôi chỉ muốn nêu mã hóa rõ ràng, thay vì để máy chủ đưa ra các giả định.
Cuối cùng, bạn đã đề cập rằng trong phpMyAdmin, bạn đã chèn chuỗi và nó trông như mong đợi - bạn có chắc chắn rằng các trang phpMyAdmin là UTF8 không? Tôi không nghĩ họ là như vậy. Khi tôi lưu trữ dữ liệu UTF8 từ mã PHP của mình, nó sẽ xem như các ký tự 8-bit thô trong phpMyAdmin. Nếu tôi lấy cùng một chuỗi và lưu trữ trực tiếp trong phpMyAdmin, thì nó có vẻ 'đúng'. Vì vậy, tôi đoán phpMyAdmin đang sử dụng bộ ký tự mặc định của máy chủ cục bộ của tôi, không nhất thiết phải là UTF8.
Ví dụ:chuỗi sau được lưu trữ từ trang web của tôi:
I can¹t wait
Đọc như thế này trong phpMyAdmin của tôi:
I can’t wait
Vì vậy, hãy cẩn thận khi kiểm tra theo cách đó, vì bạn không thực sự biết phpMyAdmin đang sử dụng cách mã hóa nào cho hiển thị hoặc kết nối DB.
Nếu bạn vẫn gặp sự cố, hãy thử mã của tôi bên dưới. Đầu tiên, tôi tạo một bảng để lưu trữ văn bản trong UTF8:
CREATE TABLE IF NOT EXISTS `utf8_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`my_text` varchar(8000) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Và đây là một số PHP để kiểm tra nó. Về cơ bản, nó lấy đầu vào của bạn trên một biểu mẫu, lặp lại đầu vào đó cho bạn và lưu trữ / truy xuất văn bản từ DB. Như tôi đã nói, nếu bạn xem dữ liệu trực tiếp trong phpMyAdmin, bạn có thể thấy nó không giống ngay ở đó, nhưng thông qua trang bên dưới, nó sẽ luôn xuất hiện như mong đợi, do kết nối trang &db đều bị khóa với UTF8.
<?php
// Override whatever is set in php.ini
ini_set('default_charset', 'UTF-8');
// The following should not be required with the above override
//header('Content-Type:text/html; charset=UTF-8');
// Open the database
$dbh = new PDO('mysql:dbname=utf8db;host=127.0.0.1;charset=utf8', 'root', 'password');
// Set the connection to UTF8
$dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
// Tell MySql to do the parameter replacement, not PDO
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// Throw exceptions (and break the code) if a query is bad
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$id = 0;
if (isset($_POST["StoreText"]))
{
$stmt = $dbh->prepare('INSERT INTO utf8_test (my_text) VALUES (:my_text)');
$stmt->execute(array(':my_text' => $_POST['my_text']));
$id = $dbh->lastInsertId();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
<title>UTF-8 Test</title>
</head>
<body>
<?php
// If something was posted, output it
if (isset($_POST['my_text']))
{
echo "POSTED<br>\n";
echo $_POST['my_text'] . "<br>\n";
}
// If something was written to the database, read it back, and output it
if ($id > 0)
{
$stmt = $dbh->prepare('SELECT my_text FROM utf8_test WHERE id = :id');
$stmt->execute(array(':id' => $id));
if ($result = $stmt->fetch())
{
echo "STORED<br>\n";
echo $result['my_text'] . "<br>\n";
}
}
// Create a form to take some user input
echo "<FORM NAME=\"utf8-test\" METHOD=\"POST\" ACTION=\"utf8-test.php\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">";
echo "<br>";
echo "<textarea name=\"my_text\" rows=\"20\" cols=\"90\">";
// If something was posted, include it on the form
if (isset($_POST['my_text']))
{
echo $_POST['my_text'];
}
echo "</textarea>";
echo "<br>";
echo "<INPUT TYPE = \"Submit\" Name = \"StoreText\" VALUE=\"Store It\" />";
echo "</FORM>";
?>
<br>
</body>
</html>