أهم أخطاء مطوري PHP المبتدئين: المستوى المتقدم
عندما تنتقل من البرامج النصية البسيطة إلى تطبيقات الويب المعقدة بلغة PHP، يزداد عدد المزالق بشكل كبير. يرتكب العديد من المطورين، بعد إتقان بناء الجملة الأساسي، أخطاء نظامية تؤدي إلى تسرب الذاكرة والثغرات الأمنية وانخفاض الأداء. في هذه المقالة، سنحلل 4 أخطاء متقدمة شائعة بين مطوري المستوى المتوسط، ونوضح كيفية إصلاحها.
1. إدارة الجلسات غير الصحيحة وتسرب الذاكرة
أحد أكثر الأخطاء غدراً هو التعامل غير الصحيح مع الجلسات. يخزن العديد من المطورين كميات كبيرة من البيانات في الجلسات (مثل نتائج استعلامات قاعدة البيانات أو الكائنات المسلسلة). هذا لا يبطئ العمل فحسب، بل قد يؤدي أيضاً إلى تسرب الذاكرة على الخادم.
المشكلة: يتم حظر الجلسة أثناء تنفيذ البرنامج النصي. إذا قمت بتخزين 10 ميغابايت من البيانات فيها، فسيقرأ كل طلب ويكتب هذا الحجم، وفي حالة الطلبات المتزامنة، سيتم وضعها في قائمة انتظار.
مثال على كود سيء:
<?phpsession_start();// تحميل مصفوفة من 10000 سجل في الجلسة$_SESSION['big_data'] = $db->query("SELECT * FROM logs")->fetchAll();?>الحل: استخدم الجلسات فقط للتعريف (user_id، token). قم بتخزين جميع البيانات الأخرى في ذاكرة التخزين المؤقت (Redis، Memcached) أو في قاعدة البيانات.
<?phpsession_start();$_SESSION['user_id'] = $user->id;// الحصول على البيانات عند الطلب$cache = new RedisCache();$data = $cache->get('user_data_' . $user->id);if (!$data) { $data = $db->query("SELECT * FROM logs WHERE user_id = ?", [$user->id])->fetchAll(); $cache->set('user_data_' . $user->id, $data, 3600);}?>2. التخزين المؤقت غير الصحيح وتجاهل الإبطال
ثاني أكثر الأخطاء شيوعاً هو التخزين المؤقت "إلى الأبد". يضع المطورون مدة حياة ذاكرة التخزين المؤقت (TTL) لمدة 24 ساعة أو أكثر، ثم يتفاجأون لماذا يرى المستخدمون بيانات قديمة. والأسوأ من ذلك هو التخزين المؤقت دون مراعاة التغييرات في قاعدة البيانات.
المشكلة: إذا قمت بتخزين قائمة المنتجات مؤقتاً لمدة ساعة، وقام المسؤول بتغيير السعر، فسيرى المستخدمون السعر القديم لمدة 60 دقيقة أخرى.
مثال على كود سيء:
<?php$cacheKey = 'product_list';$products = $cache->get($cacheKey);if (!$products) { $products = $db->query("SELECT * FROM products")->fetchAll(); $cache->set($cacheKey, $products, 86400); // 24 ساعة}?>الحل: استخدم وضع العلامات على ذاكرة التخزين المؤقت أو الإبطال القسري عند تغيير البيانات.
<?php// عند تحديث منتجfunction updateProduct($id, $data) { $db->update("products", $data, ["id" => $id]); // إبطال ذاكرة التخزين المؤقت $cache->delete('product_list'); $cache->delete('product_' . $id);}
// عند القراءة$products = $cache->remember('product_list', 3600, function() use ($db) { return $db->query("SELECT * FROM products WHERE active = 1")->fetchAll();});?>3. حقن SQL عبر دوال "آمنة"
يعتقد العديد من المطورين أنهم إذا استخدموا mysqli_real_escape_string() أو addslashes()، فإنهم محميون من حقن SQL. هذا اعتقاد خاطئ خطير. هذه الدوال لا تحمي من جميع أنواع الهجمات، خاصة عند العمل مع LIKE و ORDER BY و LIMIT.
المشكلة: الدالة mysqli_real_escape_string() لا تقوم بتسلسل الأحرف الخاصة بعامل LIKE (مثل % و _). إذا قمت بإدخال إدخال المستخدم في LIKE، يمكن للمهاجم الوصول إلى بيانات لا ينبغي له رؤيتها.
مثال على الثغرة الأمنية:
<?php$search = $_GET['q'];$safe = mysqli_real_escape_string($conn, $search);$query = "SEL