PHP-DI في PHP: دليل شامل مع أمثلة تطبيقية

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

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

ابدأ الدورة

مقدمة عن 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)

مثال:

توصيات