01/10/2018, 09:26

Cho em hỏi về MySQL, PDO

e đang làm project để cuối tháng bảo vệ, em làm trên localhost thì tạo data charset là utf8_unicode_ci rồi, rồi code php để insert dữ liệu vào thì nó không lưu tiếng việt ví dụ sản phẩm tên “Áo khoác” thì nó lưu là "Áo khoác " , nhưng khi select ra vẫn là có dấu tiếng việt đúng.

nay em up lên vps chạy nginx thử thì nó ko ra tiếng việt như trên local mà ra "Áo khoác " ( giống trong data ).

như vậy là sao ạ, ai chỉ em cách fix đc ko ạ.
em kết nối PDO và mọi table đều là utf8_unicode_ci

vũ xuân quân viết 11:32 ngày 01/10/2018

Thử dùng utf8_general_ci.

Ice Tea viết 11:29 ngày 01/10/2018

####1. Để select, insert dữ liệu tiếng Việt vào database bằng PDO bạn cần đặt charset khi khởi tạo PDO:

$host = '127.0.0.1';
$db   = 'test';
$user = 'user';
$pass = 'pass';
$charset = 'utf8'; // Unicode please

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $user, $pass, $opt);

####2. Để hiển thị tiếng Việt trên web, bạn cần set thẻ meta cho html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>

</body>
</html>

Charset của table là utf8_unicode_ci thì đúng rồi. Bạn xem có làm sai chỗ nào không? Nếu không được thì đưa code của bạn lên cho mọi người xem cho.

Bạn có thể xem thêm cách dùng PDO chi tiết tại đây ==> https://viblo.asia/pht/posts/Do754EvLKM6

Hoàng Văn Duy viết 11:26 ngày 01/10/2018

giờ thay charset của data thành general hả a

Hoàng Văn Duy viết 11:39 ngày 01/10/2018

không được anh ạ, vẫn select ra kí tự y như trong data chứ k encode sang có dấu đc

Ice Tea viết 11:38 ngày 01/10/2018

Dữ liệu đó bị lỗi rồi, bạn thử insert dữ liệu mới xem thế nào. Show code phần insert lên đây mình xem cho.

Hoàng Văn Duy viết 11:38 ngày 01/10/2018

$ten_dm = $_POST[‘ten_dm’];
$trang_thai = 0;
if(isset($_POST[‘trang_thai’]))
{
$trang_thai = 1;
}
$query = “INSERT INTO danh_muc(ten_dm, trang_thai) VALUES(’$ten_dm’,$trang_thai)”;
$count = $db->exec($query);
if($count > 0)
{
header(‘location: ds_dm.html’);
}

Hoàng Văn Duy viết 11:28 ngày 01/10/2018

à , trên localhost mình thêm charset=utf8 vào kết nối thì klhi thêm tiếng việt nó vẫn lưuw tiếng việt và khi select cũng được.

nhưng mình không hiểu tại sao khi không có charset=utf8 trong kết nối, trên local thì lưu dạng ko phải utf8 nhưng khi select ra vẫn là utf8 mà khi up lên hosting thì select ra không ra utf8.

thế là giờ mk phải insert lại từ đầu

Ice Tea viết 11:29 ngày 01/10/2018

Môi trường khác biệt bạn ạ, có thể ở localhost bạn để database mặc định character set là utf8 hoặc config của MySQL được set mặc định charset là utf8 nhưng trên hosting thì không.

$ten_dm = $POST[‘tendm’];
$trang_thai = 0;
if(isset($POST[‘trangthai’])) {
$trang_thai = 1;
}
$query = “INSERT INTO danh_muc(ten_dm, trang_thai) VALUES(’$ten_dm’,$trang_thai)”;
$count = $db->exec($query);
if($count > 0) {
header(‘location: ds_dm.html’);
}


Code của bạn bị lỗi SQL Injection nhé, bạn nên sử dụng [Prepared Statement](https://viblo.asia/pht/posts/Do754EvLKM6#prepared-statements-tr-nh-l-i-sql-injections-4) đối với các câu lệnh sử dụng biến bên ngoài kiểu này.
Phan Hoang viết 11:38 ngày 01/10/2018

Việc hiển thị không đúng tiếng Việt có thể do 1 vài yếu tố. Trước mắt chúng ta làm rõ các encoding:
1- Encoding phía mysql server. Với các phiên bản mới như MySQL 5.6, 5.7 thì charset mặc định là utf8, tuy nhiên với các phiên bản cũ thì có thể được set sang Swedish (ISO-8859-1)
2- Khi gửi câu query thì encoding gì?
3- Khi nhận result về thì encoding gì?
3- Khi lấy được result, hiển thị lên web thidung encoding gì?

Trở về trường hợp của bạn,

1- Phía local, mình đoán 1 trong các encoding của bạn không phải utf8 (có thể bạn quên gọi truyền charset vào DSN, hoặc server encoding kiểu khác), thế nên khi ghi vào CSDL và view trên Navicat/hoặc view bằng mysql_client mặc định (view trên PHPMyAdmin lại khác nhé) thì bị sai encoding nên hiển thị sai mặc dù codepage ghi vào đúng. Bạn cứ tưởng tượng, bạn ghi ký tự A là codepage 100, nhưng sang encoding mới nó là lại Á. Thế nhưng khi lấy về, nó vẫn lấy đúng codepage và nếu set ở HTML charset=“utf8” thì hiển thị vẫn đúng.

Còn lần sau bạn thử với DSN có utf8, do encoding của bảng không đúng nên nó hiển thị lỗi, nhưng trả về lại là encoding utf8 nên bạn thấy đúng. Lúc này, kể cả html bạn không cần để charset=“utf8” vẫn ok.

2- Còn phía hosting, thì trường đó có thể để utf8, nhưng do bạn đẩy query lên lại không phải utf8 nên khi lưu vào db vẫn không đúng (ví dụ chữ  của ISO-8859-1, nhưng sang utf8 lại là ô. Thế nên Áo khoác bên ISO-8859-1 sang utf8 lại là Áo khoác) Khi bạn lấy về, tất nhiên codepage vẫn thế, nhưng lại tùy result set encode gì, rồi hiển thị trên HTML charset gì mà nó hiển thị không đúng (ví dụ, result vẫn là utf8 và charset html vẫn là utf8 thì hiển nhiên nó hiển thị Áo khoác rồi. Nhưng nếu bạn set charset của html là “ISO-8859-1” thì lại hiển thị đúng ^^)

Theo mình, nếu tốt nhất nên đồng bộ UTF8 ở cả 3 nơi:

1- Các table và text encoding bằng utf8 (general hay unicode cũng được, nó chỉ khác nhau về sắp xếp). Sau mình test query, làm procedure … cũng dễ dàng hơn (thậm chí sửa db bằng tay)

2- Add utf8 vào server và client command (vào DSN hoặc gọi SET NAMES utf8).
Việc gọi SET NAMES utf8 sẽ tương đương với (ngoài ra có thể gọi thêm collation để làm sort)
SET character_set_client = x; //query gọi lên được hiểu là encoding utf8
SET character_set_results = x; //result trả về cũng là encoding utf8
SET character_set_connection = x; // char của kết nối cũng là utf8
(hoặc SET CHARACTER SET utf8. Cái này thì nó khác ở chỗ SET collation_connection = @@collation_database;)

3-Mặc định browser cũng sẽ tự detect encoding, tuy nhiên nhiều browser cơ chế detect cũng không tốt. Do đó mình cứ set 1 cái directive charset=“utf8” cho yên tâm luôn.

Bài liên quan
0