رفع مشکل نمایش/ذخیره بهم ریخته حروف فارسی در Database
علت اصلی این مشکل اینه که کدگذاری صفحه ای که اطلاعات رو از دیتابیس میخونه یا توی دیتابیس ذخیره میکنه، با کدگذاری خود دیتابیس سازگار نیست. البته عوامل دیگری هم اینجا نقش دارن. مثلاً ممکنه نوع کدگذاری مناسب برای ذخیره حروف فارسی توی دیتابیس انتخاب نشده باشه. اما راه حل قطعی و نهایی رفع این مشکل چیه؟ مراحل زیر رو انجام بدین تا به مشکل بر نخورین:
1- موقع ساخت جداول توی دیتابیس، نوع Collation رو روی utf8_bin یا utf8_persian_ci ذخیره کنید. اولی برای وقتی خوبه که بخواین بتونین علاوه بر حروف فارسی، تمام حروف Unicode رو توی دیتابیس ذخیره کنید (مثل حروف چینی و هندی و...) و دومی مخصوص زبان فارسی هست و بقیه کارکترهای Unicode رو پشتیبانی نمیکنه. تفاوت دیگه این دو مورد اینه که اولی Case Sensitive هست و دومی نه! یعنی چی؟ یعنی اینکه utf8_bin به بزرگی و کوچکی حروف حساسه و مثلاً موقع جستجو توی دیتابیس، ALI با ali فرق میکنه اما دومی اینطور نیست و از نظر اون، ALI و ali و aLi و... همه با هم یکی هستن. به عبارت دیگه، utf8_persian_ci همونطور که پسوند آخرش میگه، Case Insensitive هست (یعنی غیر حساس به بزرگی و کوچکی حروف). ازطرفی utf8_persian_ci تنها کدگذاری هست که حروف فارسی رو درست مرتب میکنه و برای مثال، پ بعد از ی نمیاد (با تشکر از دوستم rezakho بابت یادآوری این مطلب)
2- توی صفحه وبتون یکی از این دو کد رو بگذارین:
اگه از HTML4 استفاده میکنید:
کد HTML:
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
و اگه از HTML5 استفاده میکنید:
کد HTML:
<meta charset="utf-8"/>
3- صفحه رو با یک ادیتور خوب مثل ++Notepad و... با کدگذاری UTF-8 without BOM ذخیره کنید.
4- بعد از اتصال به دیتابیس (یعنی بعد از دستورات mysql_connect و mysql_select_db) این دستور رو بنویسید:
mysql_query('SET NAMES \'utf8\'');
این دستور به موتور MySQL میگه که اطلاعات مبادله شده بین موتور MySQL و مفسر PHP از کدگذاری Unicode استفاده میکنن. اگه این دستور رو نگذارین، شاهد کارکترهای عجیب و غریب بجای حروف فارسی خواهید بود و اگه خیلی شانس بیارین، یکسری مربع یا علامت سؤال ? بجای حروف فارسی میبینید.
5- این مورد در اصل برای رفع مشکل نمایش درست حروف فارسی نیست و با رعایت همون 4 مورد بالا، مشکل فوق رفع میشه. این مورد پنجم برای مواقعی هست که بخواین با کمک توابعی مثل mysql_real_escape_string جلوی حمله های SQL Injection رو به سایتتون بگیرین. در اینگونه موارد باید دقت کنید که دستور 'SET NAMES 'utf8 توی MySQL که توی مرحله قبلی با کمک تابع mysql_query اجراش میکنید، فقط نوع کدگذاری اطلاعات مبادله شده بین موتور MySQL و مفسر PHP رو مشخص میکنه و کدگذاری عملیاتی MySQL رو تغییر نمیده. برای مثال، تابعی مثل mysql_real_escape_string که عمل خنثی کردن کدهای خطرناک (Escapeکردن) رو انجام میده، کماکان از کدگذاری استاندارد یعنی iso-8859-1 استفاده میکنه. درنتیجه، چون حروف فارسی Unicode توی این کدگذاری مشخص نشده، اونها رو بعنوان کد مخرب میشناسه و از توی رشته ای که بعنوان پارامتر برای تابع مذکور فرستادیم، حذف میکنه. برای رفع این مشکل، همونطور که احتمالاً حدس زدین، باید کدگذاری عملیاتی MySQL رو عوض کنیم که این کار به راحتی با دستور زیر انجام میشه (کافیه این دستور رو بعد از دستور مرحله 4 بنویسین) :
mysql_set_charset('utf8');