php - mysqli_set_charset




UTF-8 على طول الطريق من خلال (10)

أود إضافة شيء واحد إلى جواب chazomaticus الممتاز :

لا تنس علامة META (مثل هذا ، أو إصدار HTML4 أو XHTML ):

<meta charset="utf-8">

هذا يبدو تافهاً ، لكن IE7 قد أعطاني مشاكل في ذلك من قبل.

كنت أفعل كل شيء على ما يرام ؛ تم تعيين كل من قاعدة البيانات واتصال قاعدة البيانات ورأس Content-Type HTTP على UTF-8 ، وعملت بشكل جيد في جميع المتصفحات الأخرى ، ولكن لا يزال Internet Explorer يصر على استخدام ترميز "أوروبا الغربية".

لقد تبين أن الصفحة كانت تفتقد علامة META. مضيفا أن حل المشكلة.

تصحيح:

يحتوي W3C بالفعل على قسم كبير مخصص لـ I18N . لديهم عدد من المقالات ذات الصلة بهذه المشكلة - تصف جوانب HTTP و (X) HTML و CSS للأشياء:

يوصون باستخدام كل من رأس HTTP وعلامة HTML الوصفية (أو تصريح XML في حالة استخدام XHTML كـ XML).

أقوم بإعداد خادم جديد ، وأريد دعم UTF-8 بالكامل في تطبيق الويب الخاص بي. لقد جربت في الماضي على الخوادم الموجودة ، ودائما ما ينتهي الأمر بضرورة الرجوع إلى ISO-8859-1.

أين أحتاج بالضبط إلى تعيين الترميز / charsets؟ أنا على دراية بأنني بحاجة إلى تهيئة Apache و MySQL و PHP للقيام بذلك - هل هناك بعض القوائم المرجعية القياسية التي يمكنني اتباعها ، أو ربما تحري الخلل وإصلاحه في مكان حدوث عدم التطابق؟

هذا لخادم لينكس جديد ، يشغل MySQL 5 و PHP 5 و Apache 2.


أولا وقبل كل شيء إذا كنت في <5.3PHP ثم لا. لديك الكثير من المشاكل للتعامل معها.

أنا مندهش من عدم ذكر أي مكتبة intl ، التي لديها دعم جيد ل unicode ، graphemes ، عمليات سلسلة ، توطين والكثير غيرها ، انظر أدناه.

سوف أقتبس بعض المعلومات حول دعم unicode في PHP بواسطة slides Elizabeth Smith في PHPBenelux'14

INTL

جيد:

  • التفاف حول مكتبة ICU
  • لغات موحدة ، قم بتعيين الإعدادات المحلية لكل نص
  • تنسيق الأرقام
  • تنسيق العملة
  • تنسيق الرسالة (يحل محل gettext)
  • التقاويم والتواريخ والمنطقة الزمنية والوقت
  • Transliterator
  • Spoofchecker
  • حزم الموارد
  • محولات
  • دعم IDN
  • حرف من حروف اللغة
  • الترتيب
  • المكررات

سيئة:

  • لا يدعم zend_multibite
  • لا يدعم تحويل مخرجات HTTP المدخلات
  • لا يدعم وظيفة الحمولة الزائدة

mb_string

  • تمكن دعم zend_multibyte
  • يدعم شفافية HTTP في / خارج الترميز
  • يوفر بعض wrappers ل funtionallity مثل strtoupper

يكونف

  • أساسي لتحويل charset
  • معالج إخراج المخزن المؤقت
  • وظيفة ترميز mime
  • تحويلات
  • بعض مساعدين السلسلة (len، substr، strpos، strrpos)
  • فلتر الدفق stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

قواعد بيانات

  • mysql: Charset وترتيبها على الجداول وعلى الاتصال (وليس الترتيب). أيضا لا تستخدم mysql - msqli أو PDO
  • postgresql: pg_set_client_encoding
  • sqlite (3): تأكد من أنه تم تجميعها مع unicode ودعم intl

بعض Gotchas أخرى

  • لا يمكنك استخدام أسماء ملفات Unicode مع PHP والنوافذ ما لم تستخدم ملحق جزء 3.
  • إرسال كل شيء في ASCII إذا كنت تستخدم exec و proc_open ومكالمات سطر الأوامر الأخرى
  • النص العادي ليس نص عادي ، الملفات لها ترميزات
  • يمكنك تحويل الملفات على الطاير باستخدام مرشح iconv

سأقوم بتحديث هذه الإجابة في حال تمت إضافة عناصر تغيير الأشياء وما إلى ذلك.


الجواب الأعلى ممتاز. في ما يلي ما كان يجب أن أقوم به في إعداد نظام debian / php / mysql عادي:

// storage
// debian. apparently already utf-8

// retrieval
// the mysql database was stored in utf-8, 
// but apparently php was requesting iso. this worked: 
// ***notice "utf8", without dash, this is a mysql encoding***
mysql_set_charset('utf8');

// delivery
// php.ini did not have a default charset, 
// (it was commented out, shared host) and
// no http encoding was specified in the apache headers.
// this made apache send out a utf-8 header
// (and perhaps made php actually send out utf-8)
// ***notice "utf-8", with dash, this is a php encoding***
ini_set('default_charset','utf-8');

// submission
// this worked in all major browsers once apache
// was sending out the utf-8 header. i didnt add
// the accept-charset attribute.

// processing
// changed a few commands in php, like substr,
// to mb_substr

هذا كل شئ !


الشيء الوحيد الذي أود أن أضيف إلى هذه الإجابات المدهشة هو التأكيد على حفظ الملفات في ترميز utf8 ، لقد لاحظت أن المتصفحات تقبل هذه الخاصية على إعداد utf8 كرمز الترميز الخاص بك. سيعرض لك أي محرر نص لائق هذا ، على سبيل المثال يحتوي برنامج Notepad ++ على خيار قائمة لتضمين الملف ، ويعرض لك التشفير الحالي ويتيح لك تغييره. بالنسبة لجميع ملفات php الخاصة بي ، أستخدم utf8 بدون BOM.

في وقت ما ، كان لدي شخص ما يطلب مني إضافة دعم utf8 لتطبيق php / mysql تم تصميمه من قبل شخص آخر ، لاحظت أن جميع الملفات قد تم ترميزها في ANSI ، لذلك اضطررت لاستخدام ICONV لتحويل جميع الملفات وتغيير جداول قاعدة البيانات لاستخدام جمع utf8 charset و utf8_general_ci ، قم بإضافة "SET NAMES utf8" إلى طبقة تجريد قاعدة البيانات بعد الاتصال (في حالة استخدام 5.3.6 أو ما قبل ذلك ، يجب عليك استخدام charset = utf8 في سلسلة الاتصال) وتغيير وظائف السلسلة لاستخدام php multibyte سلسلة وظائف معادلة.


بالإضافة إلى تعيين default_charset في php.ini ، يمكنك إرسال الحرف الصحيح باستخدام header() من داخل التعليمة البرمجية ، قبل أي إخراج:

header('Content-Type: text/html; charset=utf-8');

يعد العمل مع Unicode في PHP أمرًا سهلاً طالما أنك تدرك أن معظم وظائف السلسلة لا تعمل مع Unicode ، وقد يعمل البعض على تقطيع الجمل تمامًا . تعتبر PHP أن "الأحرف" هي 1 بايت. في بعض الأحيان يكون ذلك على ما يرام (على سبيل المثال ، explode() فقط يبحث عن تسلسل بايت ويستخدمه كفاصل - لذلك لا يهم ما الأحرف الفعلية التي تبحث عنها). ولكن في أوقات أخرى ، عندما تكون الوظيفة مصممة بالفعل للعمل على الأحرف ، لا يوجد لدى PHP أي فكرة عن أن نصك يحتوي على أحرف متعددة البايت موجودة مع Unicode.

مكتبة جيدة للتحقق في phputf8 . هذا يعيد كتابة جميع الوظائف "السيئة" حتى تتمكن من العمل بأمان على سلاسل UTF8. هناك امتدادات مثل امتداد mbstring الذي يحاول القيام بذلك نيابة عنك أيضًا ، لكنني أفضل استخدام المكتبة لأنها أكثر قابلية للحركة (لكني أكتب منتجات السوق الشامل ، لذلك هذا مهم بالنسبة لي). ولكن phputf8 يمكنه استخدام mbstring من وراء الكواليس ، على أي حال ، لزيادة الأداء.


في PHP ، ستحتاج إلى استخدام وظائف multibyte أو تشغيل mbstring.func_overload . بهذه الطريقة ستعمل أشياء مثل strlen إذا كان لديك أحرف تأخذ أكثر من بايت واحد.

ستحتاج أيضًا إلى تحديد مجموعة أحرف ردودك. يمكنك استخدام AddDefaultCharset ، على النحو الوارد أعلاه ، أو كتابة كود PHP الذي يقوم بارجاع الرأس. (أو يمكنك إضافة علامة META إلى مستندات HTML الخاصة بك.)


لا يزال دعم Unicode في PHP فوضى كبيرة. في حين أنه قادر على تحويل سلسلة ISO8859 (التي تستخدمها داخليا) إلى utf8 ، فإنه يفتقر إلى القدرة على العمل مع سلاسل unicode أصلا ، مما يعني أن جميع وظائف معالجة السلسلة سوف تقوض وتفسد سلاسلك. لذلك عليك إما استخدام مكتبة منفصلة لدعم utf8 الصحيح ، أو إعادة كتابة جميع وظائف معالجة السلسلة بنفسك.

الجزء السهل هو فقط تحديد الحرف في رؤوس HTTP وفي قاعدة البيانات وما شابه ، ولكن لا شيء من ذلك يهم إذا كان كود PHP لا يخرج UTF8 صالحًا. هذا هو الجزء الصعب ، و PHP يمنحك عمليا أي مساعدة هناك. (أعتقد أنه من المفترض أن يقوم PHP6 بإصلاح أسوأ ما في الأمر ، ولكن هذا لا يزال بعيدًا)


لقد اكتشفت مؤخرًا أن استخدام strtolower() يمكن أن يسبب مشكلات عند اقتطاع البيانات بعد حرف خاص.

كان الحل هو استخدام

mb_strtolower($string, 'UTF-8');

يستخدم mb_ MultiByte. وهو يدعم المزيد من الشخصيات ولكن بشكل عام أبطأ قليلاً.


هدف جيد من البداية - استنادًا إلى طبيعة موقعك ، وجدت الكثير من الموارد حول هذا الأمر من قِبل Googling - أنت لست أول من يتعامل معها ، بالطبع.

من المفترض أن يكون PHP6 الصوفي قد استرد كل هذا ، أليس كذلك؟

يمكنك تعيين utf-8 إلى حد كبير كحرف افتراضي افتراضي لـ mysql على مستوى الخادم وسيتغير بشكل صحيح إلى المستويات الأكثر دقة.


تخزين البيانات :

  • حدد مجموعة الحروف utf8mb4 على كل الجداول وأعمدة النص في قاعدة البيانات الخاصة بك. وهذا يجعل MySQL يقوم فعليًا بتخزين واسترجاع القيم المشفرة أصلاً في UTF-8. لاحظ أن MySQL ستستخدم ضمنيًا ترميز utf8mb4 إذا تم تحديد ترتيب utf8mb4_* (بدون أي مجموعة حروف صريحة).

  • في الإصدارات الأقدم من MySQL (<5.5.3) ، ستضطر للأسف لاستخدام utf8 ببساطة ، والتي تدعم فقط مجموعة فرعية من أحرف Unicode. أتمنى لو كنت تمزح.

الوصول إلى البيانات :

  • في رمز التطبيق (مثل PHP) ، وبأي طريقة من طرق الوصول إلى DB التي تستخدمها ، ستحتاج إلى تعيين charset connection إلى utf8mb4 . وبهذه الطريقة ، لا تقوم MySQL بأي تحويل من UTF-8 الأصلي الخاص بها عندما تقوم بإيصال البيانات إلى التطبيق الخاص بك والعكس بالعكس.

  • توفر بعض برامج التشغيل الآلية الخاصة بها لتكوين مجموعة أحرف الاتصال ، والتي تقوم بتحديث حالتها الداخلية الخاصة وإعلام MySQL بالترميز المستخدم في الاتصال - وهذا عادةً هو الأسلوب المفضل. في PHP:

    • إذا كنت تستخدم طبقة تجريد PDO مع PHP ≥ 5.3.6 ، فيمكنك تحديد charset في DSN :

      $dbh = new PDO('mysql:charset=utf8mb4');
      
    • إذا كنت تستخدم mysqli ، فيمكنك الاتصال set_charset() :

      $mysqli->set_charset('utf8mb4');       // object oriented style
      mysqli_set_charset($link, 'utf8mb4');  // procedural style
      
    • إذا كنت عالقا مع mysql عادي ولكن يحدث أن تشغيل PHP ≥ 5.2.3 ، يمكنك الاتصال mysql_set_charset .

  • إذا لم يقدم برنامج التشغيل آلية خاصة به لإعداد مجموعة أحرف الاتصال ، فقد يتعين عليك إصدار استعلام لإخبار MySQL كيف يتوقع التطبيق الخاص بك أن يتم ترميز البيانات على الاتصال: SET NAMES 'utf8mb4' .

  • وينطبق نفس الاعتبار فيما يتعلق بـ utf8mb4 / utf8 على النحو الوارد أعلاه.

الإخراج :

  • إذا كان التطبيق الخاص بك ينقل نصًا إلى أنظمة أخرى ، فسيلزم أيضًا إعلامك بترميز الأحرف. باستخدام تطبيقات الويب ، يجب إعلام المستعرض بالتشفير الذي يتم إرسال البيانات إليه (من خلال رؤوس استجابة HTTP أو بيانات HTML الوصفية ).

  • في PHP ، يمكنك استخدام الخيار php.ini default_charset ، أو إصدار رأس Content-Type MIME يدويًا بنفسك ، وهو مجرد عمل أكثر ولكن له نفس التأثير.

الإدخال :

  • لسوء الحظ ، يجب عليك التحقق من كل سلسلة تم استلامها باعتبارها صالحة UTF-8 قبل محاولة تخزينها أو استخدامها في أي مكان. يقوم mb_check_encoding() الخاص بـ PHP mb_check_encoding() الحيلة ، ولكن يجب عليك استخدامه دينياً. لا توجد طريقة فعلية لذلك ، حيث يستطيع العملاء الخبيثون إرسال البيانات في أي تشفير يريدونه ، ولم أجد خدعة للحصول على PHP للقيام بذلك نيابة عنك.

  • من قراءتي لمواصفات HTML الحالية ، ليست الرموز الفرعية التالية ضرورية أو صالحة حتى الآن للغة HTML الحديثة. ما أفهمه هو أن المتصفحات ستعمل مع البيانات وترسلها في مجموعة الأحرف المحددة للمستند. ومع ذلك ، إذا كنت تستهدف إصدارات قديمة من HTML (XHTML ، HTML4 ، وما إلى ذلك) ، فقد تظل هذه النقاط مفيدة:

    • بالنسبة إلى HTML قبل HTML5 فقط : تريد أن تكون جميع البيانات التي ترسلها إليك المتصفحات في UTF-8. للأسف ، إذا ذهبت بالطريقة الوحيدة للقيام بذلك بشكل موثوق ، فقم بإضافة سمة accept-charset إلى كافة علامات <form> الخاصة بك: <form ... accept-charset="UTF-8"> .
    • بالنسبة إلى HTML قبل HTML5 فقط : لاحظ أن مواصفات W3C HTML تنص على أنه يجب على العملاء "افتراضيًا" إرسال النماذج مرة أخرى إلى الخادم في أي مجموعة خادوم يقدمها الخادم ، ولكن هذه على ما يبدو توصية فقط ، ومن ثم الحاجة إلى أن تكون صريحة في كل نسخة علامة <form> .

اعتبارات قانون أخرى :

  • من الواضح أن جميع الملفات التي ستخدمها (PHP ، HTML ، جافا سكريبت ، وما إلى ذلك) يجب أن تكون مشفرة في UTF-8 صالحة.

  • تحتاج إلى التأكد من أنه في كل مرة تقوم فيها بمعالجة سلسلة UTF-8 ، يمكنك القيام بذلك بأمان. هذا هو ، للأسف ، الجزء الصعب. ربما ستحتاج إلى استخدام واسع النطاق mbstring لـ PHP.

  • عمليات السلسلة المضمنة في PHP لا تكون آمنة UTF-8 بشكل افتراضي. هناك بعض الأشياء التي يمكنك القيام بها بأمان مع عمليات سلسلة PHP العادية (مثل تسلسل) ، ولكن بالنسبة لمعظم الأشياء يجب عليك استخدام وظيفة mbstring المكافئة.

  • لمعرفة ما تفعله (اقرأ: لا تعبث به) ، يجب عليك معرفة UTF-8 وكيف يعمل على أدنى مستوى ممكن. تحقق من أي روابط من utf8.com للحصول على بعض الموارد الجيدة لتعلم كل ما تحتاج إلى معرفته.





utf-8