แบนเนอร์

วันพฤหัสบดีที่ 19 พฤษภาคม พ.ศ. 2559

MySQL แก้ปัญหา ภาษาไทย กลายเป็น ???

ตั้งค่า MySQL แก้ปัญหา ภาษาไทย กลายเป็น ??? หรือ อ่านไม่ออก

      
       รับรองว่าหลายๆคนต้องเคยเจอปัญหากับภาษาไทยเป็นเครื่องหมายคำถาม ?? กันมาแล้ว

ซึ่งสาเหตุมีเพียงเรื่องเดียวคือเรื่องของ charset ของ database

แต่เอ๊ะ ทำไมแก้ยังไงก็ไม่ได้ซะที ทั้งๆที่โฮสเก่าก็ใช้ได้ แต่โฮสใหม่ก็ทำเหมือนๆกันแต่ใช้ไม่ได้
มาดูกันครับว่าอะไรเป็นอะไร

เริ่มต้นตั้งแต่การติดตั้ง mysql

          ใน การติดตั้ง mysql-server นั้นหากไม่มีการระบุ charset ใดๆ ก็จะมี default charset เป็น latin1_swedish_ci หากมีการระบุตอน compile ก็จะเป็น charset ตามที่ระบุไว้ อย่างไรก็ดีค่า default-charset สามารถเปลี่ยนแปลงภายหลังได้โดยการระบุไว้ในไฟล์ my.cnf

เมื่อ เราทำการสร้าง database ใหม่ database ก็จะมี charset ตามค่า default ในไฟล์ my.cnf หรือถ้าใน my.cnf ไม่มีการระบุก็จะเป็นค่า default ตอน compile
compile php with mysql

        ในการ compile php นั้นเราจะต้อง configure --with-mysql=path เมื่อ compile เสร็จแล้ว สิ่งที่ได้รับคือ php จะทำการ connect mysql ด้วย charset ตามค่า default charset ของ mysql lib ซึ่งจะไม่สามารถเปลี่ยนได้ด้วย my.cnf หรือ php.ini

การตั้งค่าและการใช้งาน

แบบที่ 1
-- compile mysql เป็น default charset latin1
-- ไม่มีการกำหนด default charset ใน my.cnf
-- สร้าง database ใหม่ก็จะได้ charset เป็น latin1
-- เวลาใช้งาน php ก็ connect ด้วย charset latin1 ตาม mysql lib
-- ผลลัพธ์คือ การเก็บข้อมูลแบบ ascii ในตารางแบบ ascii
-- การใช้งานหน้าเว็บ ปกติ (encoding tis-620 หรือ windows-874)
-- phpmyadmin เวอร์ชั่น 2.5 แสดงผลเป็นภาษาไทย 
-- phpmyadmin เวอร์ชั่น >2.7 แสดงผลเป็น ascii encoding iso-8559-1 


แบบที่ 2
-- compile mysql เป็น default charset latin1
-- แล้วกำหนด default charset ใน my.cnf เป็น utf8
-- สร้าง database ใหม่ก็จะได้ charset เป็น utf8 ตาม my.cnf
-- แต่เวลาใช้งาน php ดัน connect ด้วย charset latin1 ตาม mysql lib
-- ผลลัพธ์คือ การเก็บข้อมูลแบบ ascii ในตารางแบบ unicode
-- การใช้งานหน้าเว็บ ปกติ (encoding tis-620 หรือ windows-874)
-- phpmyadmin เวอร์ชั่น 2.5 แสดงผลเป็นภาษาไทย 
-- phpmyadmin เวอร์ชั่น >2.7 แสดงผลเป็น ascii encoding iso-8559-1 

แบบที่ 3
-- compile mysql เป็น default charset utf8
-- กำหนดหรือไม่กำหนด default charset ใน my.cnf เป็น utf8 ก็ได้
-- สร้าง database ใหม่ก็จะได้ charset เป็น utf8
-- เวลาใช้งาน php ก็ connect ด้วย charset utf8 ตาม mysql lib
-- ผลลัพธ์คือ การเก็บข้อมูลแบบ unicode ในตารางแบบ unicode
-- การใช้งานหน้าเว็บ ปกติ (encoding utf-8)
-- phpmyadmin เวอร์ชั่น 2.5 แสดงผลเป็น ?? 
-- phpmyadmin เวอร์ชั่น >2.7 แสดงผลเป็น ภาษาไทย 

แบบที่ 4
-- compile mysql เป็น default charset utf8
-- กำหนดหรือไม่กำหนด default charset ใน my.cnf เป็น utf8 ก็ได้
-- สร้าง database ใหม่ก็จะได้ charset เป็น utf8
-- เวลาใช้งาน php ก็ connect ด้วย charset utf8 ตาม mysql lib
-- ผลลัพธ์คือ การเก็บข้อมูลแบบ unicode ในตารางแบบ unicode
-- การใช้งานหน้าเว็บไปใช้กับระบบที่เป็น encoding tis-620 
-- phpmyadmin เวอร์ชั่น 2.5 แสดงผลเป็น ?? 
-- phpmyadmin เวอร์ชั่น >2.7 แสดงผลเป็น ภาษาไทย 
หมาย เหตุ: แก้ encoding หน้าเว็บเป็น utf-8 ก็จะใช้งานได้ปกติ แต่จริงๆคือการเอา script แบบ ascii มาใช้ในระบบ unicode ผลที่จะตามมาคือขนาดของ field ในแต่ละตารางจะกำหนดไว้สั้นเกินไปเนื่องจาก utf-8 ใช้เนื้่อที่มากกว่าแบบ ascii 3 เท่า

แบบที่ 5
-- compile mysql เป็น default charset latin1
-- แล้วกำหนด default charset ใน my.cnf เป็น utf8
-- รวมถึงกำหนด init ใน my.cnf เป็น utf8 ด้วย
Code: [Select]
init-connect='SET collation_connection = utf8_general_ci'
init-connect='SET NAMES utf8'
-- สร้าง database ใหม่ก็จะได้ charset เป็น utf8 ตาม my.cnf
-- และเวลาใช้งาน php จะ connect ด้วย utf8 ตาม init-connect ใน my.cnf
-- ผลลัพธ์คือ การเก็บข้อมูลแบบ unicode ในตารางแบบ unicode
-- การใช้งานหน้าเว็บ ปกติ (encoding utf-8)
-- phpmyadmin เวอร์ชั่น 2.5 แสดงผลเป็น ?? 
-- phpmyadmin เวอร์ชั่น >2.7 แสดงผลเป็น ภาษาไทย 

ขอแสดงตัวอย่างแค่ 5 แบบที่น่าจะพบมากที่สุดพอครับ


ผลกระทบ
     ใน แต่ละแบบจะเห็นว่าระบบจะบังคับการใช้งานไปใน charset ใด charset หนึ่ง ซึ่งหากต้องการใช้งานระบบที่ต่างจาก default charset  ที่ตั้งค่าไว้ จะต้องกำหนดใน code php หลังจากทำการ connect และ select database แล้ว ดังนี้
Code: [Select]
mysql_query("SET NAMES 'charset_name' COLLATE 'collation_name';");
เช่น
mysql_query("SET NAMES 'utf8' COLLATE 'utf8_general_ci';");
หรือ
mysql_query("SET NAMES 'tis620' COLLATE 'tis620_thai_ci';");
หรือ
mysql_query("SET NAMES 'latin1' COLLATE 'latin1_swedish_ci';");

การแก้ปัญหา

      สำหรับ ระบบที่ติดตั้งใหม่ ไม่น่าจะมีปัญหามากนัก หากติดตั้งแล้วไม่แสดงผลอย่างที่ควรเป็น ก็ให้ตรวจสอบ collation ของ Database ที่สร้างใหม่ให้ตรงกับที่ต้องการก่อนที่จะทำการติดตั้ง script และก็ให้ทำการเพิ่มคำสั่ง
Code: [Select]
mysql_query("SET NAMES 'charset_name' COLLATE 'collation_name';");เข้าไปก็น่าจะหมดปัญหา

สำหรับ ระบบที่ใช้งานอยู่แล้วไม่มีปัญหาแต่มีปัญหาตอนย้ายโฮส ก็คงต้องหาข้อแตกต่างระหว่าง 2 server ออกมา โดยไล่ดูการตั้งค่าต่างๆของทั้ง 2 server ดังนี้
-- default charset ของ mysql lib
-- default charset ใน my.cnf
-- มีการกำหนด init connect ใน my.cnf หรือไม่
-- php connect ด้วย default charset อะไร
-- Database ที่สร้างไว้มี collation อะไร
-- Table ต่างๆใน database มี charset อะไร สอดคล้องกับ collation หรือไม่
-- ข้อมูลที่เก็บอยู่ใน table เก็บลักษณะใหน charset อะไร แสดงผลถูกต้องหรือไม่ (ทั้ง phpmyadmin และ หน้าเว็บ)
-- หน้าเว็บแสดงผลด้วย encoding อะไร
-- ข้อมูลที่ export ออกมาเป็น .sql export ด้วยวิธีใหน mysqldump, phpmyadmin เวอร์ชั่นอะไร, bigdump, ...
-- ไฟล์ .sql เปิดอ่านด้วย text editor อ่านออกหรือไม่ (แนะนำให้ใช้ notepad++ แล้วลองเปลี่ยน Format / Encoding ดูด้วย)

กรณีที่มีการ import หรือ Export ข้อมูลให้เลือกเป็น tis620
1.2 กำหนด Header ให้ใช้เป็น tis-620 (กำหนดในไฟล์เว็บของเรานะคับ)
<meta http-equiv=Content-Type content="text/html; charset=tis-620">

1.3โค๊ดในส่วนของ Connection

- กรณีที่กำหนด Collation เป็น tis620_thai_ci ให้ใช้
$objConnect = mysql_connect("localhost","root","root") or die("Error Connect to Database");
$objDB = mysql_select_db("mydatabase");
mysql_query("SET NAMES TIS620");

- กรณีที่กำหนด Collation อื่น ๆ ให้ใช้
$objConnect = mysql_connect("localhost","root","root") or die("Error Connect to Database");
$objDB = mysql_select_db("mydatabase");
mysql_query("SET character_set_results=tis620");//ตั้งค่าการดึงข้อมูลออกมาให้เป็น tis620
mysql_query("SET character_set_client=tis620");//ตั้งค่าการส่งข้อมุลลงฐานข้อมูลออกมาให้ เป็น tis620
mysql_query("SET character_set_connection=tis620");//ตั้งค่าการติดต่อฐานข้อมูลให้เป็น tis620

กรณีที่มีการ import หรือ Export ข้อมูลให้เลือกเป็น utf8

2.2 กำหนด Header ให้ใช้เป็น utf-8
<meta http-equiv=Content-Type content="text/html; charset=utf-8">

2.3
กำหนดในส่วนของ Connection

- กรณีที่กำหนด Collation เป็น utf8_unicode_ci ให้ใช้
$objConnect = mysql_connect("localhost","root","root") or die("Error Connect to Database");
$objDB = mysql_select_db("mydatabase");
mysql_query("SET NAMES UTF8");

- กรณีที่กำหนด Collation อื่น ๆ ให้ใช้
$objConnect = mysql_connect("localhost","root","root") or die("Error Connect to Database");
$objDB = mysql_select_db("mydatabase");
mysql_query("SET character_set_results=utf8");//ตั้งค่าการดึงข้อมูลออกมาให้เป็น utf8
mysql_query("SET character_set_client=utf8");//ตั้งค่าการส่งข้อมุลลงฐานข้อมูลออกมาให้เป็น utf8
mysql_query("SET character_set_connection=utf8");//ตั้งค่าการติดต่อฐานข้อมูลให้เป็น utf8

จะเห็นว่าสามารถรองรับใช้ภาษาไทยได้ทั้ง 2 รูปแบบ
แต่อย่างไรก็ตามอยากจะแนะนำให้เปลี่ยนให้เป็น UTF-8 ให้หมดครับ เพราะมันดีกว่าหลาย ๆ ด้าน และก็จะช่วยขจัดปัญหาในการที่เราเอา ฐานข้อมูลไปใช้กับ server อื่นๆ รวมทั้งการเช่า host ด้วย

เครดิตข้อมูลจาก thaicreate.com

อ่านเรื่อง charset เพิ่มเติมได้ที่ http://www.thaihosttalk.com/th1/index.php?topic=6764.msg63194#msg63194
บทความที่เกี่ยวข้อง http://www.itwizard.info/technology/MySQL/MySQL_with_thai.html


ไม่มีความคิดเห็น:

แสดงความคิดเห็น