لماذا تتحول أحرفك العربية إلى "الععبية" وكيف تصلحها نهائياً
\n\nهل سبق لك أن فتحت موقعك المكتوب بلغة PHP وبدلاً من رؤية "مرحباً بالعالم!" وجدت نصاً مشوهاً مثل الععبية؟ إذا كانت الإجابة بنعم — فهنيئاً لك، لقد واجهت المشكلة الكلاسيكية UTF-8 all the way through. هذا الموقف الذي يحدث عندما ينكسر الترميز في مكان ما بين قاعدة البيانات والمتصفح، والجميع مسؤول ولكن لا أحد يريد تحمل المسؤولية.
على Stack Overflow، حصد هذا السؤال آلاف المشاهدات ومئات الإجابات. وليس من دون سبب. حتى المطورين المخضرمين أحياناً يختلط عليهم الأمر في إعدادات الترميز. في هذا الدليل، سنشرح وصفة خطوة بخطوة لجعل PHP وMySQL والمتصفح يعملون معاً، بحيث يعمل UTF-8 في كل مكان ودائماً. لا سحر — فقط إعدادات صحيحة.
\n\nالخطوة 1. قاعدة البيانات: أساس الترميز الخاص بك
\n\nكل شيء يبدأ من قاعدة البيانات. إذا كانت بياناتك في MySQL مخزنة بترميز latin1 أو cp1256 (للغة العربية)، وتحاول عرضها بترميز UTF-8 — ستحصل على نصوص مشوشة. ولكن حتى لو كانت قاعدة البيانات بترميز UTF-8، هناك فارق بسيط: الترميز القديم utf8 في MySQL لا يدعم الرموز التعبيرية (Emoji) وبعض الأحرف النادرة. الحل هو utf8mb4.
1.1. إنشاء الجداول بالترميز الصحيح
\n\nعند إنشاء جدول جديد، حدد دائماً:
\n\nCREATE TABLE articles (\n id INT AUTO_INCREMENT PRIMARY KEY,\n title VARCHAR(255) NOT NULL,\n content TEXT NOT NULL\n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nبديل آخر هو تعيين الترميز الافتراضي لقاعدة البيانات بأكملها:
\n\nALTER DATABASE your_database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nهام: utf8mb4_unicode_ci هو collation (قاعدة مقارنة). يتعامل بشكل صحيح مع جميع أحرف يونيكود. إذا لم تكن بحاجة إلى ترتيب حسب لغات مختلفة، فإن utf8mb4_general_ci كافٍ أيضاً.
1.2. تحويل الجداول الموجودة
\n\nإذا كان لديك بالفعل بيانات بترميز آخر، قم أولاً بتحويلها:
\n\nALTER TABLE articles CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nلكن كن حذراً: إذا كانت البيانات في الجدول مخزنة أصلاً بترميز latin1، فقد تتحول إلى ترميز مزدوج (مثل الععبية). في هذه الحالة، تحتاج أولاً إلى تحويل الأعمدة إلى binary ثم إلى utf8mb4. هذه قصة منفصلة، لكن للتبسيط، سنفترض أنك تبدأ من الصفر.
الخطوة 2. اتصال PHP بقاعدة البيانات: إعداد PDO
\n\nفي PHP الحديثة، تستخدم PDO (أو mysqli). وهناك نقطة حرجة: بعد الاتصال بقاعدة البيانات، يجب تحديد الترميز بشكل صريح. وإلا، سيتواصل PHP مع MySQL بالترميز الافتراضي (غالباً latin1).
\n\n2.1. سلسلة اتصال PDO الصحيحة
\n\n$host = 'localhost';\n$dbname = 'your_database';\n$username = 'root';\n$password = '';\n\n$dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4";\n\n$options = [\n PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n PDO::ATTR_EMULATE_PREPARES => false,\n];\n\ntry {\n $pdo = new PDO($dsn, $username, $password, $options);\n} catch (PDOException $e) {\n echo "فشل الاتصال: " . $e->getMessage();\n}\n\nلاحظ استخدام charset=utf8mb4 في DSN. هذا يجبر PHP وMySQL على الاتفاق على الترميز على مستوى الاتصال.
2.2. طريقة بديلة (إذا لم يعمل DSN)
\n\nأحياناً، الإصدارات القديمة من PHP أو الخوادم لا تقرأ charset من DSN. في هذه الحالة، أضف بعد الاتصال:
\n\n$pdo->exec("SET NAMES 'utf8mb4'");\n\nلكن الطريقة الأولى هي الأفضل — فهي أنظف وأكثر حداثة.
\n\nالخطوة 3. رؤوس HTTP وHTML: أخبر المتصفح بالحقيقة
\n\nحتى لو كانت قاعدة البيانات وPHP يعملان بترميز UTF-8، قد يقرر المتصفح أن