حقن SQL في PHP: كيفية الحماية في 2025

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

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

ابدأ الدورة

مقدمة: لماذا لا تزال هجمات حقن SQL خطيرة في 2025؟

\n\n

تخيل أن موقعك يعمل بسلاسة، المستخدمون يسجلون، يتركون تعليقات، ويطلبون منتجات. وفجأة — تقع قاعدة البيانات في أيدي مخترق. ليس لأن المخترقين عباقرة، بل لأن أحدهم نسي وضع علامة استفهام في استعلام SQL.

\n\n

هجمات حقن SQL ليست تهديدًا قديمًا من العقد الأول من الألفية. في عام 2024، لا تزال OWASP تضعها ضمن أخطر 3 ثغرات في تطبيقات الويب. وسؤال "How can I prevent SQL injection in PHP?" على Stack Overflow حصل على أكثر من 1.5 مليون مشاهدة — وما زال في ازدياد. هذا يعني أن المشكلة لا تزال قائمة.

\n\n

في هذا المقال، سنشرح بالتفصيل كيف تسدّ الباب بإحكام أمام هجمات حقن SQL في PHP لعام 2025. بدون سحر، بدون أطر عمل معقدة، فقط كود نظيف وأفضل الممارسات.

\n\n

ما هو حقن SQL بلغة بسيطة؟

\n\n

حقن SQL هو عندما يصبح إدخال المستخدم جزءًا من أمر SQL، وليس مجرد بيانات. مثال من الواقع:

\n\n
<?php\n// كود سيّئ — لا تفعل هذا أبدًا!\n$username = $_POST['username'];\n$query = "SELECT * FROM users WHERE username = '$username'";\n$result = mysqli_query($conn, $query);\n?>
\n\n

إذا أدخل المخترق في حقل username النص ' OR '1'='1، سيتحول الاستعلام إلى:

\n\n
SELECT * FROM users WHERE username = '' OR '1'='1'
\n\n

هذا سيعيد جميع المستخدمين. وإذا أدخل '; DROP TABLE users; -- — فقد تفقد الجدول بأكمله. مخيف، أليس كذلك؟

\n\n

أفضل ممارسات الحماية من حقن SQL في PHP 2025

\n\n

1. استخدم PDO مع الاستعلامات المُعدة (هذا هو المعيار)

\n\n

PDO (PHP Data Objects) هي واجهة عالمية للتعامل مع قواعد البيانات. ميزتها الرئيسية: تفصل منطق SQL عن البيانات. تكتب الاستعلام مع عناصر نائبة (placeholders)، وPDO يتولى عملية الهروب الآمن بنفسه.

\n\n
<?php\n// كود جيد — استخدم PDO\n$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';\n$pdo = new PDO($dsn, $user, $pass, [\n    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n    PDO::ATTR_EMULATE_PREPARES => false, // تعطيل المحاكاة\n]);\n\n$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');\n$stmt->execute(['email' => $_POST['email']]);\n$user = $stmt->fetch();\n?>
\n\n

لماذا يعمل هذا؟ قاعدة البيانات تستقبل هيكل الاستعلام بشكل منفصل عن البيانات. حتى لو أدخل المستخدم كود SQL ضار، سيتم تفسيره كنص عادي وليس كجزء من الأمر.

\n\n

2. Mysqli مع الاستعلامات المُعدة (بديل)

\n\n

إذا كنت تعمل مع MySQL فقط، يمكنك استخدام mysqli — ولكن فقط مع الاستعلامات المُعدة، وليس مع الهروب عبر mysqli_real_escape_string().

\n\n
<?php\n$mysqli = new mysqli('localhost', 'user', 'pass', 'testdb');\n$stmt = $mysqli->prepare('INSERT INTO comments (user_id, text) VALUES (?, ?)');\n$stmt->bind_param('is', $userId, $commentText);\n$stmt->execute();\n?>
\n\n

هام: في عام 2025، لا يزال mysqli_real_escape_string() موجودًا، لكن الاعتماد عليه للحماية فكرة سيئة. فهو يهرب النصوص فقط، لكنه لا يحمي من الحقن في الحقول الرقمية أو في عوامل LIKE.

\n\n

3. التصفية والتحقق — خط الدفاع الثاني

\n\n

الاستعلامات المُعدة هي الأساس. لكن أضف إليها التصفية حسب نوع البيانات. إذا كان المتوقع رقمًا — تحقق من أنه رقم. إذا كان بريدًا إلكترونيًا — تحقق من الصيغة.

\n\n
<?php\n$id = filter_input(INPUT_POST, 'user_id', FILTER_VALIDATE_INT);\nif ($id === false) {\n    throw new InvalidArgumentException('يجب أن يكون المعرف عددًا صحيحًا');\n}\n\n$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');\n$stmt->execute(['id' => $id]);\n?>
\n\n

اجمع بين

المدونات

توصيات الكتب