حقن التبعية في PHP: دليل كامل مع أمثلة برمجية

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

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

ابدأ الدورة

حقن التبعية في PHP: عمليًا

\n\n

حقن التبعية (DI) — أحد المبادئ الأساسية لـ SOLID، والذي يسمح بكتابة كود مرن وقابل للاختبار والصيانة. في هذه المقالة، سنشرح كيفية تنفيذ حقن التبعية في PHP بأمثلة واقعية، دون نظريات مجردة. ستتعلم كيفية التخلص من الروابط الصلبة بين الكلاسات وجعل كودك جاهزًا للتغييرات.

\n\n

ما هو حقن التبعية ولماذا هو ضروري؟

\n\n

تخيل أن لديك كلاس UserController يعمل مع قاعدة البيانات. بدون DI، غالبًا ما تقوم بإنشاء كائن الاتصال مباشرة داخل المتحكم:

\n\n
class UserController {\n    private $db;\n    public function __construct() {\n        $this->db = new MySQLConnection('localhost', 'user', 'pass');\n    }\n}
\n\n

هذا الأسلوب يُنشئ رابطًا صلبًا (tight coupling). إذا أردت التبديل إلى PostgreSQL أو استخدام كائن وهمي للاختبارات، ستحتاج إلى تغيير كود المتحكم. يحل حقن التبعية هذه المشكلة: يتم تمرير التبعيات من الخارج، بدلاً من إنشائها داخل الكلاس.

\n\n

المزايا الرئيسية لـ DI:

\n
    \n
  • تقليل ترابط الكود
  • \n
  • تبسيط الاختبار (سهولة استبدال التبعيات)
  • \n
  • إعادة استخدام الكلاسات
  • \n
  • هندسة نظيفة والالتزام بمبدأ عكس التبعية (DIP)
  • \n
\n\n

طرق حقن التبعية في PHP

\n\n

هناك ثلاث طرق رئيسية لحقن التبعيات. سنستعرض كل منها مع أمثلة.

\n\n

1. الحقن عبر المُنشئ

\n\n

الطريقة الأكثر شيوعًا والموصى بها. يتم تمرير التبعيات عبر بارامترات المُنشئ وتخزينها في خصائص الكلاس.

\n\n
<?php\ninterface DatabaseInterface {\n    public function query(string $sql): array;\n}\n\nclass MySQLDatabase implements DatabaseInterface {\n    public function query(string $sql): array {\n        // المنطق الفعلي للعمل مع MySQL\n        return ['id' => 1, 'name' => 'John'];\n    }\n}\n\nclass UserRepository {\n    private DatabaseInterface $db;\n    \n    public function __construct(DatabaseInterface $db) {\n        $this->db = $db;\n    }\n    \n    public function getUser(int $id): array {\n        return $this->db->query("SELECT * FROM users WHERE id = $id");\n    }\n}\n\n// الاستخدام:\n$db = new MySQLDatabase();\n$repo = new UserRepository($db);\n$user = $repo->getUser(1);\n?>
\n\n

لاحظ: نحن نستخدم الواجهة DatabaseInterface. هذا يسمح باستبدال التنفيذ بسهولة — على سبيل المثال، باستخدام كائن اختبار وهمي.

\n\n

2. الحقن عبر السيتيرات

\n\n

تُستخدم عندما لا تكون التبعية ضرورية في مرحلة إنشاء الكائن أو قد تتغير أثناء العمل.

\n\n
<?php\nclass MailService {\n    private ?MailerInterface $mailer = null;\n    \n    public function setMailer(MailerInterface $mailer): void {\n        $this->mailer = $mailer;\n    }\n    \n    public function send(string $to, string $subject, string $body): void {\n        if ($this->mailer === null) {\n            throw new \\RuntimeException('Mailer not configured');\n        }\n        $this->mailer->send($to, $subject, $body);\n    }\n}\n\n// الاستخدام:\n$mailService = new MailService();\n$mailService->setMailer(new SmtpMailer());\n$mailService->send('user@example.com', 'Hello', 'Body');\n?>
\n\n

عيب هذه الطريقة — لا تضمن أن التبعية سيتم تعيينها قبل استدعاء الدالة send(). لذلك، للتبعيات الإلزامية يُفضل استخدام المُنشئ.

\n\n

3. الحقن عبر الدالة

\n\n

يتم تمرير التبعية مباشرة إلى الدالة التي تحتاجها. مفيد للتبعيات النادرة أو السياقية.

\n\n
<?php\nclass ReportGenerator {\n    public function generate(DataFetcherInterface $fetcher, string $reportType): array {\n        $data = $fetcher->                

المدونات

توصيات الكتب