理解PHP依賴注入容器系列(二) 你需要
在上一篇中我們透過一個具體的Web案例來說明依賴注入,今天我們將談到依賴注入的容器(Container),首先讓我們從一個重要的聲明開始:
大多數時侯,你在使用依賴注入方式解耦元件時,並不需要用到容器。
但是如果你要管理很多不同的對象,並且要處理複雜繁多的對象間的依賴關係時,容器就變得很有用了。
還記得第一篇的範例嗎,在建立User物件前要先建立一個SessionStorage物件。這沒什麼大不了,但我還是想說,這是因為你在創建你所需要的對象之前,你清楚的知道它所依賴的對象了。如果物件很多,依賴關係很複雜(假設SessionStorage類別依賴cache類,cache類別依賴file類別和inputFilter類別,file類別依賴stdio類別),那就呵呵了。 。 。 。
$storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
在後面的文章中我們將介紹Symfony 2中實現容器的方式。不過現在為了能簡單、清楚的說明容器,我們先無視Symfony。以下將採用 Zend Framework中的一個範例來說明:
Zend Framework 的Zend_Mail類別簡化了email管理,它預設使用PHP的mail()函數來傳送郵件,但是彈性欠佳。不過謝天謝地,可以透過提供transport類別來輕鬆改變這些行為。
下面的程式碼展示如何建立Zend_Mail類別並使用Gmail帳號來傳送郵件
$transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, )); $mailer = new Zend_Mail(); $mailer->setDefaultTransport($transport);
依賴注入容器(Dependency Injection Container)是一個大類,它能實例化並配置他所管理的各種元件和類別。為了能做到這些,它必須知道這些類別的建構方法的參數,依賴關係。
下面是一個硬編碼的容器,還是實現之前所提到的獲取Zend_Mail對象的工作:
class Container { public function getMailTransport() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, )); } public function getMailer() { $mailer = new Zend_Mail(); $mailer->setDefaultTransport($this->getMailTransport()); return $mailer; } } //容器的使用也很简单 $container = new Container(); $mailer = $container->getMailer();
在使用容器的時侯,如果需要獲得一個Zend_Mail對象,並不需要知道創建它的細節,因為所有創建對象實例的細節都內建到容器中實現了。 Zend_Mail對Mail_Transport類別的依賴也能透過容器自動注入Zend_Mail物件中。
取得依賴物件主要是getMailTransport()實作的,容器的強大之處就是靠這個簡單的get呼叫實現的。
但是聰明的你一定發現了問題,容器裡面有硬編碼(如,發送郵件的帳號密碼資訊等)。所以我們要更進一步,為容器加入參數,讓容器變得更有用。
class Container { protected $parameters = array(); public function __construct(array $parameters = array()) { $this->parameters = $parameters; } public function getMailTransport() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => $this->parameters['mailer.username'], 'password' => $this->parameters['mailer.password'], 'ssl' => 'ssl', 'port' => 465, )); } public function getMailer() { $mailer = new Zend_Mail(); $mailer->setDefaultTransport($this->getMailTransport()); return $mailer; } }
現在透過容器建構函數的參數可以很容易切換發送郵件的帳號和密碼
$container = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', )); $mailer = $container->getMailer();
如果覺得Zend_Mail類不能滿足當前需要(比如測試時,需要做一些日誌),想輕易切換郵件發送類,同樣可以透過容器建構函數的參數傳遞類別名稱
class Container { // ... public function getMailer() { $class = $this->parameters['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransport()); return $mailer; } } $container = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', 'mailer.class' => 'MyTest_Mail', )); $mailer = $container->getMailer();
最後,考慮到客戶取得mailer物件時並不需要每次都重新實例化一下(佔用開銷),容器應該每次提供相同的物件實例。
因此,程式使用了protected的靜態陣列$shared,用來儲存第一次實例化的物件,以後使用者取得mailer時都會傳回第一次實例化的物件
class Container { static protected $shared = array(); // ... public function getMailer() { if (isset(self::$shared['mailer'])) { return self::$shared['mailer']; } $class = $this->parameters['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransport()); return self::$shared['mailer'] = $mailer; } }
容器封裝了這些基本功能,容器需要管理的內容包括物件的實例化和配置。這些物件本身並不知道自己被容器管理,也可以無視容器的存在。這也就是為什麼容器可以管理任何PHP類別。如果物件本身在對依賴關係的處理使用了依賴注入這種方式就更好了,當然這不是必須的。
不過手工創建和維護容器很快會變成噩夢。後面的文章講會講述Symfony 2是怎麼實現容器的。
以上就是理解PHP依賴注入容器系列(二) 你需要的內容,更多相關內容請關注PHP中文網(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。
