مقدمة عن PHP-DI: ما هو ولماذا تحتاجه
PHP-DI (PHP Dependency Injection) هي مكتبة قوية لحقن التبعيات (Dependency Injection) في تطبيقات PHP. تطبق هذه المكتبة نمط عكس التحكم (Inversion of Control - IoC) وتوفر حاوية لحل التبعيات بين الكلاسات تلقائياً.
لماذا تحتاج PHP-DI؟ في مشاريع PHP الحديثة (خاصة على إطارات العمل مثل Laravel و Symfony و Slim)، تعتمد الكلاسات غالباً على كلاسات أخرى. بدون حاوية DI، ستضطر لإنشاء جميع التبعيات يدوياً، مما يؤدي إلى:
- ارتباط محكم للكود (tight coupling)
- صعوبة في الاختبار
- تكرار الكود عند إنشاء الكائنات
- صعوبات في الصيانة والتوسع
PHP-DI تحل هذه المشاكل عن طريق تحديد الكلاسات التي يحتاجها كودك تلقائياً، وإنشائها مع التبعيات الصحيحة. تدعم المكتبة:
- الحقن التلقائي عبر المُنشئ (Constructor Injection)
- تحديد التبعيات عبر التعليقات التوضيحية (phpDoc)
- الإعداد عبر المصفوفات أو ملفات YAML أو PHP
- التحميل البطيء (lazy loading)
- التكامل مع إطارات العمل الشهيرة
تثبيت PHP-DI
يتم تثبيت PHP-DI عبر Composer - مدير الحزم القياسي لـ PHP:
composer require php-di/php-di
إذا كنت تستخدم إطار العمل Slim، قم بتثبيت حزمة التكامل:
composer require php-di/slim-bridge
لـ Symfony توجد حزمة منفصلة:
composer require php-di/symfony-bridge
بعد التثبيت، قم بتضمين مُحمّل Composer التلقائي في مشروعك:
require __DIR__ . '/vendor/autoload.php';
بداية سريعة مع مثال كود
لننظر إلى مثال بسيط لاستخدام PHP-DI. لنفترض أن لدينا كلاس Mailer يعتمد على كلاس Logger:
<?php
// كلاس Logger
class Logger {
public function log($message) {
echo "[LOG]: " . $message . "\n";
}
}
// كلاس Mailer الذي يعتمد على Logger
class Mailer {
private $logger;
public function __construct(Logger $logger) {
$this->logger = $logger;
}
public function send($to, $subject) {
$this->logger->log("جارٍ إرسال البريد إلى {$to}: {$subject}");
// منطق الإرسال...
}
}
// إنشاء حاوية DI
$container = new DI\Container();
// الحصول على كائن Mailer - يتم حل جميع التبعيات تلقائياً
$mailer = $container->get('Mailer');
$mailer->send('user@example.com', 'مرحباً!');
?>
في هذا المثال، تقوم PHP-DI تلقائياً بإنشاء نسخة من Logger وتمريرها إلى مُنشئ Mailer. لست بحاجة لكتابة new Logger() - الحاوية تقوم بذلك نيابة عنك.
الطرق والوظائف الأساسية لـ PHP-DI
1. Container::get() - الحصول على كائن من الحاوية
الوظيفة: تستخرج كائنًا باسمه (كلاس، واجهة، أو اسم مستعار) من الحاوية. إذا لم يتم إنشاء الكائن بعد، تقوم الحاوية بإنشائه مع جميع تبعياته.
المعاملات:
string $name- اسم الكلاس أو الواجهة أو الاسم المستعار
مثال:
$container = new DI\Container();
$logger = $container->get('Logger'); // ينشئ ويعيد كائن Logger
$mailer = $container->get('Mailer'); // ينشئ Mailer مع Logger داخله
2. Container::set() - تسجيل تعريف
الوظيفة: تسجل تعريفًا لكلاس أو واجهة أو اسم مستعار. تسمح بتحديد كيفية إنشاء الكائن بالضبط.
المعاملات:
string $name- اسم الكلاس أو الاسم المستعارmixed $definition- التعريف (نص، مصفوفة، إغلاق Closure، كائن Definition)
مثال: