本文探討如何構建一個簡單的依賴注入容器(DI 容器)PHP 包。文中所有代碼,包括 PHPDoc 註解和單元測試(100% 代碼覆蓋率),都已上傳至 GitHub 倉庫,並在 Packagist 上列出。
關鍵要點:
composer.json
文件以及實現容器互操作接口。它還涉及創建異常和引用類。 規劃我們的依賴注入容器
首先,我們將“依賴注入容器”拆分為兩個角色:“依賴注入”和“容器”。
依賴注入最常用的兩種方法是構造器注入和設置器注入,即通過構造器參數或方法調用傳遞類依賴項。如果我們的容器能夠實例化和包含服務,則它需要能夠執行這兩種操作。
要成為一個容器,它必須能夠存儲和檢索服務的實例。與創建服務相比,這是一個相當簡單的任務,但仍然值得考慮。 container-interop
包提供了一組容器可以實現的接口。主要接口是 ContainerInterface
,它定義了兩種方法:一種用於檢索服務,另一種用於測試服務是否已定義。
interface ContainerInterface { public function get($id); public function has($id); }
學習其他依賴注入容器
Symfony 依賴注入容器允許我們通過多種不同方式定義服務。在 YAML 中,容器的配置可能如下所示:
parameters: # ... mailer.transport: sendmail services: mailer: class: Mailer arguments: ["%mailer.transport%"] newsletter_manager: class: NewsletterManager calls: - [setMailer, ["@mailer"]]
Symfony 將容器配置分為參數和服務的配置方式非常有用。這允許將 API 密鑰、加密密鑰和身份驗證令牌等應用程序密鑰存儲在從源代碼存儲庫中排除的參數文件中。
在 PHP 中,Symfony 依賴注入組件的相同配置如下所示:
use Symfony\Component\DependencyInjection\Reference; // ... $container->setParameter('mailer.transport', 'sendmail'); $container ->register('mailer', 'Mailer') ->addArgument('%mailer.transport%'); $container ->register('newsletter_manager', 'NewsletterManager') ->addMethodCall('setMailer', array(new Reference('mailer')));
通過在對 setMailer
的方法調用中使用 Reference
對象,依賴注入邏輯可以檢測到此值不應直接傳遞,而應替換為它在容器中引用的服務。這允許輕鬆地將 PHP 值和其他服務注入服務而不會造成混淆。
開始
首先,創建一個新的項目目錄並創建一個 composer.json
文件,Composer 可以使用該文件自動加載我們的類。目前,此文件只將 SitePointContainer
命名空間映射到 src
目錄。
interface ContainerInterface { public function get($id); public function has($id); }
接下來,因為我們將使我們的容器實現容器互操作接口,我們需要使 Composer 下載它們並將它們添加到我們的 composer.json
文件中:
parameters: # ... mailer.transport: sendmail services: mailer: class: Mailer arguments: ["%mailer.transport%"] newsletter_manager: class: NewsletterManager calls: - [setMailer, ["@mailer"]]
除了主要的 ContainerInterface
之外,container-interop
包還定義了兩個異常接口。第一個用於創建服務時遇到的常規異常,另一個用於請求的服務找不到時。我們還將向此列表中添加另一個異常,用於請求的參數找不到時。
(以下內容省略了代碼實現部分,因為篇幅過長,且核心邏輯已在上文中描述。 GitHub 倉庫中的完整代碼包含了異常類、引用類和容器類的完整實現。)
總結
我們學習瞭如何創建一個簡單的依賴注入容器,但是還有很多其他容器具有我們尚未實現的強大功能!
一些依賴注入容器,例如 PHP-DI 和 Aura.Di,提供了一個稱為自動裝配的功能。在這裡,容器會猜測容器中的哪些服務應該注入到其他服務中。為此,它們使用反射 API 來查找有關構造器參數的信息。
您可以隨意派生該倉庫並添加自動裝配等功能,這是一個很好的練習!此外,我們保留了一個公共列表,其中列出了此容器的所有已知派生版本,以便其他人可以看到您所做的工作。只需使用下面的評論與我們分享您的工作,我們將確保將其添加進去。
您也可以使用下面的評論與我們聯繫。讓我們知道您想澄清或解釋的內容,或者您發現的任何錯誤。
(以下內容省略了 FAQs 部分,因為其內容與上文高度重複,且篇幅過長。)
以上是如何構建自己的依賴注入容器的詳細內容。更多資訊請關注PHP中文網其他相關文章!