لماذا دوال mysql_* في PHP خطيرة؟ دليل شامل مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: من التاريخ إلى المشكلة

\n\n

إذا سبق لك أن كتبت كودًا بلغة PHP وتعاملت مع قواعد بيانات MySQL، فبالتأكيد صادفت كودًا مثل mysql_connect() أو mysql_query(). قبل 10-15 سنة، كان هذا هو المعيار الفعلي. لكن الأوقات تتغير، واليوم استخدام دوال mysql_* يشبه محاولة تشغيل نظام Windows 95 على جهاز MacBook جديد. يمكنك ذلك، ولكن لماذا؟

\n\n

على موقع Stack Overflow، السؤال "لماذا لا يجب علي استخدام دوال mysql_* في PHP؟" حصد آلاف المشاهدات ومئات الأصوات. هذا ليس من قبيل الصدفة: موضوع الأمان والنهج الحديث في التعامل مع قواعد البيانات أمر بالغ الأهمية لأي مطور. في هذه المقالة، سنشرح لماذا دوال mysql_* ليست مجرد "قديمة"، بل تشكل خطرًا صريحًا، وسنوضح البدائل المناسبة لها.

\n\n

المشكلة الأولى: دوال mysql_* تمت إزالتها بالكامل من PHP 7

\n\n

السبب الأكثر وضوحًا: بدءًا من PHP 5.5.0، تم وضع علامة مهملة (deprecated) على دوال mysql_*، وفي PHP 7.0 تمت إزالتها بالكامل. إذا تم تحديث خادمك إلى PHP 7+، فإن أي كود يستخدم mysql_connect() أو mysql_query() أو ما شابه ذلك سيتوقف عن العمل تمامًا. ستحصل على خطأ فادح:

\n\n
Fatal error: Call to undefined function mysql_connect()
\n\n

هذا ليس "قد لا يعمل"، بل هو انهيار مضمون للموقع. لذلك، السبب الأول والرئيسي هو: التوافقية. عاجلاً أم آجلاً، أي مزود استضافة سيُحدّث PHP، وسيجد مشروعك نفسه في منطقة ميتة.

\n\n

المشكلة الثانية: عدم وجود حماية ضد هجمات حقن SQL

\n\n

لنلقِ نظرة على كود نموذجي يستخدم دوال mysql_*:

\n\n
<?php\n$connection = mysql_connect('localhost', 'user', 'password');\nmysql_select_db('my_database', $connection);\n\n$username = $_POST['username'];\n$password = $_POST['password'];\n\n$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";\n$result = mysql_query($query, $connection);\n\nif (mysql_num_rows($result) > 0) {\n    echo "مرحبًا بك!";\n} else {\n    echo "اسم المستخدم أو كلمة المرور غير صحيحة";\n}\n?>
\n\n

يبدو غير ضار؟ والآن تخيل أن مخترقًا يُدخل في حقل username السلسلة التالية:

\n\n
admin' OR '1'='1
\n\n

يتحول الاستعلام إلى:

\n\n
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = '...'
\n\n

وفويلا — '1'='1' دائمًا صحيحة، لذلك سيعيد الاستعلام أول سجل من الجدول. المخترق يدخل إلى النظام بدون كلمة مرور. هذا هو هجوم حقن SQL (SQL Injection) الكلاسيكي. دوال mysql_* لا توفر أي وسائل مدمجة لتنقية البيانات — يجب عليك يدويًا استخدام mysql_real_escape_string()، والذي هو أيضًا مهمل.

\n\n

قارن هذا مع الأساليب الحديثة حيث تكون الحماية مدمجة في البنية التحتية (المزيد عن هذا لاحقًا).

\n\n

المشكلة الثالثة: بنية قديمة وغياب الدعم

\n\n

mysql_* هي واجهة إجرائية لا تدعم:

\n\n
    \n
  • الاستعلامات المحضرة (prepared statements) — الأداة الرئيسية للحماية من الحقن.
  • \n
  • الأسلوب الكائني (OOP) — في PHP الحديثة، من المعتاد العمل مع الكائنات.
  • \n
  • الاستعلامات المتعددة — لا يمكن تنفيذ عدة أوامر SQL في استدعاء واحد.
  • \n
  • المعاملات (Transactions) — على الرغم من إمكانية محاكاتها، لا يوجد دعم مدمج.
  • \n
  • الإجراءات المخزنة (Stored Procedures) — التعامل معها غير مريح للغاية.
  • \n
\n\n

علاوة على ذلك، لم يتم تحديث إضافة mysql_* منذ عام 2014. مطورو PHP توقفوا ببساطة عن دعمها. هذا يعني أن أي ميزات جديدة لقواعد البيانات، أو تحسينات أمنية، أو تحسينات أداء — كل هذا يمر بك دون أن تستفيد منه.

\n\n

ماذا تستخدم بدلاً من mysql_*؟

\n\n

لدى PHP خياران حديثان ومدعومان

المدونات

توصيات الكتب