learn

رفع مشکل حروف فارسی در PHP و MySQL با UTF-8

راهنمای تشخیص محل خرابی متن فارسی و تنظیم صحیح اتصال، ذخیره‌سازی و نمایش بدون تبدیل کورکورانهٔ داده‌ها.

حروف فارسی در PHP و MySQL زمانی درست نمایش داده می‌شوند که کدگذاری فایل، ارتباط دیتابیس، ستون ذخیره‌سازی و خروجی مرورگر با هم هماهنگ باشند. افزودن یک متا یا تغییر collation برای همهٔ خطاها کافی نیست. ابتدا مشخص کنید متن در خود دیتابیس خراب است یا فقط هنگام نمایش به‌هم می‌ریزد.

تشخیص مشکل حروف فارسی در PHP و MySQL

یک متن آزمایشی مانند «سلام، آزمایش فارسی» را از مسیر واقعی برنامه ذخیره و دوباره بخوانید. مقدار ذخیره‌شده را هم جدا بررسی کنید. اگر از ابتدا علامت سؤال ذخیره شده باشد، اصلاح نمایش حروف اصلی را برنمی‌گرداند. اگر متن سالم ذخیره شده ولی مرورگر آن را ناخوانا می‌بیند، مسیر خروجی و هدر را بررسی کنید.

تفاوت شکل «ی» و «ک»، نیم‌فاصله یا جهت متن نیز همیشه مشکل کدگذاری نیست. این مسائل می‌توانند به نویسه‌های متفاوت، نرمال‌سازی یا CSS مربوط باشند. برای هرکدام راه‌حل متناسب انتخاب کنید و تبدیل سراسری روی دادهٔ اصلی انجام ندهید.

تنظیم درست اتصال mysqli

تابع mysqli_query برای ایجاد اتصال نیست. ابتدا اتصال را بسازید و سپس charset آن را تنظیم کنید. نمونهٔ زیر فرض می‌کند متغیرهای اتصال از تنظیمات خصوصی برنامه آمده‌اند؛ آن‌ها را با اطلاعات واقعی و حساب محدود به دیتابیس لازم مقداردهی کنید:

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$db = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
$db->set_charset('utf8mb4');

مستند PHP استفاده از set_charset را به اجرای دستی SET NAMES با mysqli_query ترجیح می‌دهد. این تنظیم متعلق به همان اتصال برنامه است؛ اجرای دستور در جلسهٔ جداگانهٔ phpMyAdmin، اتصال برنامهٔ شما را تغییر نمی‌دهد. ورودی کاربر را نیز با پرس‌وجوی آماده مدیریت کنید؛ charset جای جلوگیری از تزریق SQL را نمی‌گیرد.

تنظیم در PDO

اگر برنامه از PDO استفاده می‌کند، charset را در DSN مشخص کنید. این روش جایگزین نمونهٔ mysqli است، نه مرحله‌ای که باید پس از آن اجرا شود:

<?php
$dsn = 'mysql:host=' . $dbHost . ';dbname=' . $dbName . ';charset=utf8mb4';
$pdo = new PDO($dsn, $dbUser, $dbPassword, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
]);

پارامترهای میزبان و پورت باید با محیط واقعی هماهنگ باشند. راهنمای DSN در PDO گزینه‌ها را توضیح می‌دهد. خطای اتصال را در لاگ خصوصی بررسی کنید؛ جزئیات حساب را در صفحهٔ عمومی چاپ نکنید.

Charset با collation یکسان نیست

Charset شیوهٔ کدگذاری و collation قواعد مقایسه و مرتب‌سازی متن را مشخص می‌کند. utf8mb4 مجموعهٔ کامل‌تری از نویسه‌های یونیکد، از جمله نویسه‌های چهار‌بایتی، را پشتیبانی می‌کند. برای پروژهٔ جدید، آن را همراه collation سازگار با نسخهٔ MySQL یا MariaDB و نیاز برنامه انتخاب کنید.

طبق مستند تنظیم دیتابیس، پیش‌فرض دیتابیس در ایجاد جدول‌های جدید کاربرد دارد. تغییر این پیش‌فرض به معنی تبدیل خودکار تمام ستون‌های موجود نیست. ساختار جدول و ستون را جدا بررسی کنید. تبدیل ستون‌های فعلی باید ابتدا روی نسخهٔ آزمایشی انجام شود؛ نوع داده، ایندکس‌ها و encoding واقعی دادهٔ قبلی اهمیت دارند.

فایل و خروجی مرورگر

فایل منبع را با UTF-8 ذخیره کنید. برای پاسخ HTML، پیش از هر خروجی می‌توانید هدر زیر را در نقطهٔ مناسب برنامه تنظیم کنید:

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

در ابتدای head صفحه نیز اعلان charset را قرار دهید. نمونهٔ ساختار فارسی:

<!doctype html>
<html lang="fa" dir="rtl">
<head>
  <meta charset="UTF-8">
  <title>آزمایش فارسی</title>
</head>
<body>سلام</body>
</html>

اعلان UTF-8 بایت‌های از قبل خراب‌شده را تعمیر نمی‌کند. اگر متن ناخوانا ذخیره شده است، پیش از هر تبدیل، نمونهٔ خام و منشأ آن را بررسی کنید. راه‌حل عمومی و بی‌خطرِ تبدیل چندباره برای همهٔ داده‌ها وجود ندارد؛ بازیابی از منبع سالم ممکن است لازم باشد.

مطالعهٔ مرتبط

بازبینی فنی: ۱۳ آبان ۱۴۰۵. تاریخ انتشار اولیه و نشانی قبلی حفظ شده‌اند.

مطالب مرتبط

ارسال نظر

فهرست مطالب