ปัญหาการเข้ารหัสภาษาจีนในการเขียนโปรแกรม PHP สร้างปัญหาให้กับผู้คนจำนวนมาก จริงๆ แล้วสาเหตุของปัญหานี้นั้นง่ายมาก แต่ละประเทศ (หรือภูมิภาค) กำหนดชุดการเข้ารหัสอักขระสำหรับการแลกเปลี่ยนข้อมูลคอมพิวเตอร์ เช่น รหัส ASCII แบบขยายในสหรัฐอเมริกาและ GB2312 ในประเทศจีน -80, JIS ของญี่ปุ่น ฯลฯ เนื่องจากเป็นพื้นฐานสำหรับการประมวลผลข้อมูลในประเทศ/ภูมิภาคนี้ ชุดการเข้ารหัสอักขระจึงมีบทบาทสำคัญในการรวมการเข้ารหัส ชุดการเข้ารหัสอักขระแบ่งออกเป็นสองประเภทตามความยาว: SBCS (ชุดอักขระไบต์เดียว) และ DBCS (ชุดอักขระไบต์คู่) ในซอฟต์แวร์ยุคแรกๆ (โดยเฉพาะระบบปฏิบัติการ) เพื่อที่จะแก้ปัญหาการประมวลผลข้อมูลอักขระในเครื่องคอมพิวเตอร์ จึงมีการนำเวอร์ชันที่แปลเป็นภาษาท้องถิ่น (L10N) ต่างๆ มาใช้ เพื่อสร้างความแตกต่าง จึงมีการนำแนวคิดต่างๆ เช่น LANG และ Codepage มาใช้ อย่างไรก็ตาม เนื่องจากช่วงโค้ดที่ทับซ้อนกันของชุดอักขระในเครื่องต่างๆ ทำให้การแลกเปลี่ยนข้อมูลระหว่างกันเป็นเรื่องยาก ค่าใช้จ่ายในการบำรุงรักษาอิสระของซอฟต์แวร์แต่ละเวอร์ชันที่แปลเป็นภาษาท้องถิ่นจึงสูง ดังนั้นจึงจำเป็นต้องแยกสิ่งที่เหมือนกันในงานโลคัลไลเซชันและประมวลผลอย่างสม่ำเสมอเพื่อลดเนื้อหาการประมวลผลโลคัลไลซ์พิเศษให้เหลือน้อยที่สุด สิ่งนี้เรียกว่าการทำให้เป็นสากล (118N) ข้อมูลภาษาต่างๆ ได้รับการกำหนดมาตรฐานเพิ่มเติมเป็นข้อมูลสถานที่ ชุดอักขระพื้นฐานที่ประมวลผลกลายเป็น Unicode ซึ่งมีร่ายมนตร์เกือบทั้งหมด
ในปัจจุบัน การประมวลผลอักขระหลักของซอฟต์แวร์ที่มีลักษณะสากลส่วนใหญ่จะใช้ Unicode เมื่อซอฟต์แวร์กำลังทำงาน การตั้งค่าการเข้ารหัสอักขระท้องถิ่นที่เกี่ยวข้องจะถูกกำหนดตามการตั้งค่าภาษา/Lang/Codepage ในขณะนั้น และอักขระท้องถิ่น ประมวลผลตามนั้น ในระหว่างการประมวลผล จำเป็นต้องตระหนักถึงการแปลงร่วมกันระหว่าง Unicode และชุดอักขระท้องถิ่น หรือแม้แต่การแปลงร่วมกันระหว่างชุดอักขระท้องถิ่นสองชุดที่มี Unicode อยู่ตรงกลาง วิธีการนี้จะขยายออกไปอีกในสภาพแวดล้อมเครือข่าย และข้อมูลอักขระใดๆ ที่ปลายทั้งสองด้านของเครือข่ายยังจำเป็นต้องแปลงเป็นเนื้อหาที่ยอมรับได้ตามการตั้งค่าชุดอักขระด้วย
ปัญหาการเข้ารหัสชุดอักขระในฐานข้อมูล
ระบบฐานข้อมูลเชิงสัมพันธ์ยอดนิยมทั้งหมดรองรับการเข้ารหัสชุดอักขระฐานข้อมูล ซึ่งหมายความว่าคุณสามารถระบุการตั้งค่าชุดอักขระของตนเองได้เมื่อสร้างฐานข้อมูล และข้อมูลฐานข้อมูลจะถูกเก็บไว้ในการเข้ารหัสที่ระบุ เมื่อแอปพลิเคชันเข้าถึงข้อมูล จะมีการแปลงการเข้ารหัสชุดอักขระที่จุดเข้าและออก สำหรับข้อมูลภาษาจีน การตั้งค่าการเข้ารหัสอักขระฐานข้อมูลควรรับประกันความสมบูรณ์ของข้อมูล GB2312, GBK, UTF-8 ฯลฯ ล้วนเป็นการเข้ารหัสชุดอักขระฐานข้อมูลเสริม แน่นอนว่าเรายังสามารถเลือก ISO8859-1 (8 บิต) ได้ แต่เราต้องแปลงอักขระจีน 16 บิตหรือ Unicode ก่อน
แอปพลิเคชัน
เขียนข้อมูลแยกออกเป็นอักขระ 8 บิตสองตัว หลังจากอ่านข้อมูลแล้ว คุณต้องรวมทั้งสองไบต์และระบุอักขระ SBCS ไม่เพียงแต่จะไม่ได้ใช้ประโยชน์จากการสนับสนุนการเข้ารหัสชุดอักขระของฐานข้อมูลอย่างเต็มที่ แต่ยังเพิ่มความซับซ้อนของการเขียนโปรแกรมด้วย เมื่อเขียนโปรแกรม คุณสามารถใช้ฟังก์ชันการจัดการที่ได้รับจากระบบการจัดการฐานข้อมูลเพื่อตรวจสอบว่าข้อมูลภาษาจีนถูกต้องหรือไม่
ก่อนที่จะทำการสืบค้นฐานข้อมูล โปรแกรม PHP จะรัน mysql_query("SET NAMES xxxx"); โดยที่ xxxx คือการเข้ารหัสของหน้าเว็บของคุณ (charset=xxxx) หาก charset=utf8 ในหน้าเว็บ ดังนั้น xxxx=utf8 ถ้าเป็นชุดอักขระ =gb2312 ในหน้าเว็บ จากนั้น xxxx=gb2312 โปรแกรมเว็บเกือบทั้งหมดจะมีรหัสทั่วไปสำหรับเชื่อมต่อกับฐานข้อมูล ซึ่งอยู่ในไฟล์นี้ เพียงเพิ่ม mysql_query("SET NAMES xxxx")
SET NAMES แสดงชุดอักขระที่ใช้ในคำสั่ง SQL ที่ส่งโดยไคลเอ็นต์ ดังนั้นคำสั่ง SET NAMES 'utf-8' จะบอกเซิร์ฟเวอร์ว่า "ข้อมูลในอนาคตจากไคลเอนต์นี้จะใช้ชุดอักขระ utf-8" นอกจากนี้ยังระบุชุดอักขระสำหรับผลลัพธ์ที่เซิร์ฟเวอร์ส่งกลับไปยังไคลเอ็นต์ (เช่น หากคุณใช้คำสั่ง SELECT จะระบุชุดอักขระที่ใช้สำหรับค่าคอลัมน์)
เทคนิคที่ใช้กันทั่วไปในการค้นหาปัญหา
การค้นหาปัญหาการเข้ารหัสภาษาจีนมักจะใช้วิธีที่โง่ที่สุดและมีประสิทธิภาพมากที่สุด - การพิมพ์โค้ดภายในของสตริงหลังจากประมวลผลโดยโปรแกรมที่คุณคิดว่าน่าสงสัย ด้วยการพิมพ์โค้ดภายในของสตริง คุณจะทราบได้ว่าเมื่อใดที่อักขระภาษาจีนถูกแปลงเป็น Unicode เมื่อ Unicode ถูกแปลงกลับเป็นโค้ดภายในของจีน เมื่ออักขระจีนหนึ่งตัวกลายเป็นอักขระ Unicode สองตัว เมื่อสตริงภาษาจีนถูกแปลงเป็นสตริง A เครื่องหมายคำถาม บิตลำดับสูงของสตริงอักขระจีนถูกตัดทอนเมื่อใด...
การใช้สตริงตัวอย่างที่เหมาะสมสามารถช่วยแยกแยะประเภทของคำถามได้เช่นกัน ตัวอย่างเช่น: " aaahaa?@aa " และสตริงอื่นๆ ที่สลับระหว่างภาษาจีนและภาษาอังกฤษ และมีทั้งอักขระลักษณะ GB และ GBK โดยทั่วไปแล้ว อักขระภาษาอังกฤษจะไม่บิดเบี้ยวไม่ว่าจะถูกแปลงหรือประมวลผลด้วยวิธีใดก็ตาม (หากคุณพบตัวอักษรเหล่านี้ คุณสามารถลองเพิ่มความยาวของตัวอักษรภาษาอังกฤษที่ต่อเนื่องกันได้)
แก้ไขปัญหาโค้ดที่อ่านไม่ออกในแอปพลิเคชันต่างๆ
1) ใช้แท็กเพื่อตั้งค่าการเข้ารหัสหน้า
หน้าที่ของแท็กนี้คือการประกาศชุดอักขระที่เข้ารหัสที่เบราว์เซอร์ของไคลเอ็นต์ใช้เพื่อแสดงเพจ xxx สามารถเป็น GB2312, GBK, UTF-8 (แตกต่างจาก MySQL ซึ่งเป็น UTF8) เป็นต้น ดังนั้น หน้าเว็บส่วนใหญ่สามารถใช้วิธีนี้เพื่อบอกเบราว์เซอร์ว่าควรใช้การเข้ารหัสใดเมื่อแสดงหน้านี้ เพื่อหลีกเลี่ยงข้อผิดพลาดในการเข้ารหัสและอักขระที่อ่านไม่ออก แต่บางครั้งเราจะพบว่าประโยคนี้ยังคงใช้งานไม่ได้ ไม่ว่าจะเป็น xxx ใดก็ตาม เบราว์เซอร์จะใช้การเข้ารหัสเดียวกันเสมอ ฉันจะพูดถึงสถานการณ์นี้ในภายหลัง
โปรดทราบว่าข้อมูลนี้เป็นของข้อมูล HTML และเป็นเพียงคำสั่งซึ่งบ่งชี้ว่าเซิร์ฟเวอร์ได้ส่งข้อมูล HTML ไปยังเบราว์เซอร์เท่านั้น
2) header("content-type:text/html; charset=xxx");
ฟังก์ชั่นของ header() ฟังก์ชั่นนี้คือการส่งข้อมูลในวงเล็บไปยังส่วนหัว http หากเนื้อหาในวงเล็บเป็นไปตามที่กล่าวไว้ในบทความ แสดงว่าฟังก์ชันโดยพื้นฐานแล้วเหมือนกับป้ายกำกับ หากเปรียบเทียบกับอันแรกจะพบว่าอักขระคล้ายกัน แต่ข้อแตกต่างก็คือ หากมีฟังก์ชันนี้ เบราว์เซอร์จะใช้การเข้ารหัส xxx ที่คุณร้องขอเสมอและจะไม่มีวันขัดคำสั่ง ดังนั้นฟังก์ชันนี้จึงมีประโยชน์มาก เหตุใดจึงเกิดขึ้น ถ้าอย่างนั้น เราต้องพูดถึงความแตกต่างระหว่างส่วนหัว http และข้อมูล HTML:
ส่วนหัว http คือสตริงที่เซิร์ฟเวอร์ส่งก่อนที่จะส่งข้อมูล HTML ไปยังเบราว์เซอร์โดยใช้โปรโตคอล http แท็กนี้เป็นของข้อมูล HTML ดังนั้นเนื้อหาที่ส่งโดย header() จะไปถึงเบราว์เซอร์ก่อน ประเด็นยอดนิยมคือ header() มีลำดับความสำคัญสูงกว่า (ฉันไม่รู้ว่าจะพูดแบบนี้ได้ไหม) หากหน้า PHP มีทั้ง header("content-type:text/html;charset=xxx") และ header("content-type:text/html;charset=xxx") เบราว์เซอร์จะรู้จักเฉพาะส่วนหัว http เดิมและ ไม่ใช่เมตาดาต้า แน่นอนว่าฟังก์ชันนี้สามารถใช้ได้เฉพาะในหน้า PHP เท่านั้น
ยังมีคำถามอยู่ว่าเหตุใดแบบแรกจึงใช้งานได้จริง แต่บางครั้งแบบหลังใช้ไม่ได้ผล นี่คือเหตุผลที่เราจะพูดถึง Apache ต่อไป
3) AddDefaultCharset
ในโฟลเดอร์ conf ในไดเรกทอรีรากของ Apache จะมีเอกสารการกำหนดค่า Apache ทั้งหมด httpd.conf
เปิด httpd.conf ด้วยโปรแกรมแก้ไขข้อความ บรรทัด 708 (อาจแตกต่างกันในเวอร์ชันต่างๆ) มี AddDefaultCharset xxx โดยที่ xxx คือชื่อการเข้ารหัส ความหมายของบรรทัดโค้ดนี้: ตั้งค่าชุดอักขระในส่วนหัว http ของไฟล์หน้าเว็บในเซิร์ฟเวอร์ทั้งหมดเป็นชุดอักขระ xxx เริ่มต้นของคุณ การมีบรรทัดนี้เทียบเท่ากับการเพิ่มส่วนหัว ("content-type: text/html; charset=xxx") ลงในแต่ละไฟล์ ตอนนี้คุณสามารถเข้าใจได้แล้วว่าทำไมเบราว์เซอร์ถึงใช้ gb2312 เสมอ แม้ว่าจะตั้งค่าเป็น utf-8 ก็ตาม
หากมี header("content-type:text/html; charset=xxx") ในหน้าเว็บ ชุดอักขระเริ่มต้นจะถูกเปลี่ยนเป็นชุดอักขระที่คุณตั้งไว้ ดังนั้นฟังก์ชันนี้จะมีประโยชน์เสมอ หากคุณเพิ่ม "#" ไว้หน้า AddDefaultCharset xxx ให้ใส่ความคิดเห็นในประโยคนี้ และหน้านั้นไม่มีส่วนหัว ("ประเภทเนื้อหา...") แสดงว่าเมตาแท็กจะมีผล
ลำดับความสำคัญของรายการข้างต้นแสดงไว้ด้านล่าง:
.. header("content-type:text/html; charset=xxx")
.. AddDefaultCharset xxx
..
หากคุณเป็นโปรแกรมเมอร์เว็บ ขอแนะนำให้เพิ่มส่วนหัวให้กับแต่ละรายการ ของเพจของคุณ ("content-type:text/html;charset=xxx") ช่วยให้มั่นใจได้ว่าสามารถแสดงได้อย่างถูกต้องบนเซิร์ฟเวอร์ใดๆ และมีการพกพาที่แข็งแกร่ง
4) การกำหนดค่า Default_charset ใน php.ini:
default_charset = "gb2312" ใน php.ini กำหนดชุดอักขระภาษาเริ่มต้นของ php โดยทั่วไปแนะนำให้ใส่เครื่องหมายความคิดเห็นในบรรทัดนี้ และปล่อยให้เบราว์เซอร์เลือกภาษาโดยอัตโนมัติตามชุดอักขระในส่วนหัวของหน้าเว็บ แทนที่จะสร้างข้อกำหนดบังคับ เพื่อให้สามารถให้บริการเว็บในหลายภาษาบนเซิร์ฟเวอร์เดียวกันได้
ที่จริงแล้ว
การเขียนโค้ดภาษาจีนในการพัฒนา PHP นั้นไม่ได้ซับซ้อนอย่างที่คิด แม้ว่าจะไม่มีกฎตายตัวสำหรับการวางตำแหน่งและการแก้ปัญหา และสภาพแวดล้อมการทำงานต่างๆ ก็แตกต่างกัน แต่หลักการพื้นฐานก็เหมือนกัน การทำความเข้าใจความรู้เกี่ยวกับชุดอักขระเป็นพื้นฐานในการแก้ปัญหาอักขระ อย่างไรก็ตาม ด้วยการเปลี่ยนแปลงชุดอักขระภาษาจีน ไม่เพียงแต่การเขียนโปรแกรม PHP เท่านั้น แต่ยังรวมถึงปัญหาในการประมวลผลข้อมูลภาษาจีนด้วยจะยังคงมีอยู่ระยะหนึ่ง