إعادة هيكلة الكود القديم بلغة PHP: من الألف إلى الياء
العمل مع الكود القديم (legacy) هو جزء لا مفر منه في حياة أي مطور PHP. عاجلاً أم آجلاً، ستواجه مشروعًا مكتوبًا بلغة PHP 5.6 (أو حتى 4)، حيث لا يوجد تحميل تلقائي، وتُستخدم المتغيرات العامة، وتختلط منطق الأعمال مع HTML. إعادة هيكلة هذا الكود ليست مجرد "تمشيط"، بل هي عملية استراتيجية يمكنها إنقاذ المشروع من الديون التقنية وجعله قابلاً للصيانة.
في هذه المقالة، سنشرح كيفية التعامل مع إعادة هيكلة كود PHP القديم بشكل منهجي، دون كسر الوظائف الحالية، وتحويل "المستنقع" إلى كود حديث وقابل للاختبار.
1. التشخيص والتقييم: من أين نبدأ؟
قبل تغيير الكود، يجب أن تفهم ما تتعامل معه. ابدأ بمراجعة المشروع.
الخطوة 1. تحديد "نقاط الألم"
- التبعيات: هل تُستخدم مكتبات قديمة؟ على سبيل المثال، دوال
mysql_*بدلاً من PDO أو MySQLi. - الهيكلة: هل يوجد أي هيكل (MVC)؟ أم أن كل الكود في ملف واحد
index.php؟ - الاختبارات: هل توجد اختبارات آلية؟ إذا لم تكن موجودة، فهذه أولويتك الأولى.
الخطوة 2. أدوات التحليل
استخدم محللات ثابتة لتحديد المشكلات بسرعة:
- PHPStan / Psalm: ستجد أخطاء الأنواع وعدم تطابق التوقيعات.
- Rector: سيحدث بناء الجملة تلقائيًا لإصدار PHP الجديد.
- PhpMetrics: سيظهر التعقيد الدوري وتماسك الكود.
مثال على تشغيل Rector للتحديث من PHP 7.4 إلى 8.0:
vendor/bin/rector process src/ --set php802. استراتيجية "الجراحة بدون ألم": خطة خطوة بخطوة
إعادة هيكلة الكود القديم ليست "انفجارًا كبيرًا". إنها سلسلة من الخطوات الصغيرة والآمنة. استخدم تقنية "Strangler Fig" (التين الخانق) — استبدل الوحدات القديمة تدريجيًا بوحدات جديدة، دون إعادة كتابة كل شيء مرة واحدة.
الخطوة 1. قم بتغطية الكود بالاختبارات
بدون اختبارات، إعادة الهيكلة هي لعبة الروليت الروسية. ابدأ بـ اختبارات التوصيف (characterization tests):
class LegacyCalculatorTest extends TestCase { public function testOldCalculation(): void { // تشغيل الكود القديم وتسجيل النتيجة $result = legacy_calculation(10, 5); $this->assertEquals(15, $result); }}سيخلق هذا "شبكة أمان" قبل إجراء التغييرات.
الخطوة 2. اعزل المنطق "القذر"
إذا كان الكود يعمل مع المتغيرات العامة ($GLOBALS)، قم بإخراجها كمعاملات للدالة:
// كان (اعتماد عام)function processOrder() { global $db; $result = $db->query("SELECT * FROM orders");}
// أصبح (حقن التبعية)function processOrder(PDO $db) { $result = $db->query("SELECT * FROM orders");}الخطوة 3. استبدل الدوال القديمة
على سبيل المثال، استبدال mysql_* بـ PDO:
// الكود القديم$link = mysql_connect('localhost', 'user', 'pass');mysql_select_db('test', $link);$result = mysql_query("SELECT * FROM users", $link);
// الكود الجديد (PDO)$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');$stmt = $pdo->query("SELECT * FROM users");$result = $stmt->fetchAll(PDO::FETCH_ASSOC);3. المشكلات النموذجية في PHP القديم وحلولها
المشكلة 1: "كود السباغيتي" (خليط من المنطق والعرض)
الحل: قسّم الكود إلى طبقات. أخرج منطق الأعمال إلى فئات منفصلة، وHTML إلى قوالب (على سبيل المثال، باستخدام Twig).
// سيء: المنطق وHTML في ملف واحدif ($user->isAdmin()) { echo "<h1>مرحبًا، أيها المسؤول!</h1>";} else { echo "<h1>مرحبًا، أيها المستخدم!</h1>";}
// جيد: وحدة تحكم + قالب//