搜尋
首頁後端開發php教程PHP主|用丘疹注入依賴

PHP Master | Dependency Injection with Pimple

核心要點

  • 依賴注入是應用開發中的一個關鍵概念,通過將依賴項注入模塊而不是硬編碼它們,可以編寫更高效、更易維護的代碼。
  • Pimple是一個簡單的依賴注入容器,它使用PHP的閉包以可管理的方式定義依賴項,有助於保持代碼的可維護性。
  • 注入依賴項的兩種主要技術是基於構造函數的依賴注入和基於設置器的注入,每種技術都有其自身的優缺點。
  • Pimple通過充當定義依賴項的容器來支持軟件開發的DRY(不要重複自己)原則,避免重複,從而更輕鬆地管理和集中應用程序中的服務。
  • Pimple還提供高級功能,例如使用共享對象返回相同實例的能力,以及無需影響原始實現即可動態修改現有閉包的能力。

在應用程序開發中,我們嘗試創建獨立的模塊,以便在未來的項目中重用代碼。但是,創建提供有用功能的完全獨立的模塊很困難;除非正確管理它們的依賴關係,否則它們可能會導致維護噩夢。這就是依賴注入派上用場的地方,因為它使我們能夠注入代碼正常運行所需的依賴項,而無需將它們硬編碼到模塊中。 Pimple是一個簡單的依賴注入容器,它利用PHP的閉包以可管理的方式定義依賴項。在本文中,我們將探討硬編碼依賴項的問題,依賴注入如何解決這些問題,以及如何使用Pimple來使利用依賴注入的代碼更易於維護。

具體依賴項的問題

在編寫應用程序時,我們會使用許多PHP類。一個類可能需要調用一個或多個其他類的方法來提供預期的功能,因此我們說第一個類依賴於其他類。例如:

<?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}

類A依賴於類B。如果類B不可用,則上述代碼將無法工作。此外,每次我們在類中硬編碼對象的創建時,我們都會對該類產生具體的依賴關係。具體依賴關係是編寫可測試代碼的障礙。更好的方法是向類A提供類B的對象。這些對象可以通過A的構造函數或setter方法提供。在我們進一步討論之前,讓我們來看一個更現實的場景。

如今,在社交網絡網站上共享內容非常普遍,大多數網站都在其網站上直接顯示其社交資料提要。假設我們有一個名為SocialFeeds的類,它從Twitter、Facebook、Google 等社交網站生成提要。創建單獨的類來處理這些服務中的每一個。在這裡,我們將研究與Twitter交互的類TwitterService。 SocialFeeds類使用TwitterService請求Twitter提要。 TwitterService與數據庫交互以檢索訪問API的特定用戶令牌。令牌傳遞給OAuth類,該類使用提供的令牌檢索提要並將其返回給SocialFeeds類。

<?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}
<?php
class SocialFeeds
{
    public function getSocialFeeds() {
        $twService = new TwitterService();
        echo $twService->getTweets();
    }
}
<?php
class TwitterService
{
    public function getTweets() {
        $db = new DB();
        $query = "Query to get user token from database";
        $token = $db->getQueryResults($query);

        $oauth = new OAuth();
        return $oauth->requestTwitterFeed($token);
    }
}
<?php
class OAuth
{
    public function requestTwitterFeed($token) {
        // Retrieve and return twitter feed using the token         
    }
}

很明顯,SocialFeeds依賴於TwitterService。但是TwitterService依賴於DB和OAuth,因此SocialFeeds間接依賴於DB和OAuth。那麼問題是什麼呢? SocialFeeds依賴於三個類的具體實現,因此不可能在沒有其他類的真實實現的情況下單獨測試SocialFeeds。或者,假設我們想使用不同的數據庫或不同的OAuth提供程序。在這種情況下,我們必須在整個代碼中用新類替換現有類。

修復具體依賴項

解決這些依賴項問題的方案很簡單,即在必要時動態提供對象,而無需使用具體實現。有兩種類型的技術可以注入依賴項:基於構造函數的依賴注入和基於設置器的注入。

基於構造函數的注入

使用基於構造函數的依賴注入,依賴對像是在外部創建的,並作為參數傳遞給類的構造函數。我們可以將這些對象分配給類變量,並在類內任何地方使用。 SocialFeeds類的基於構造函數的注入如下所示:

<?php
class DB
{
    public function getQueryResults($query) {
        // Get results from database and return token
    }
}

TwitterService的實例作為對像傳遞給構造函數。 SocialFeeds仍然依賴於TwitterService,但現在我們可以自由地提供不同版本的Twitter服務提供程序,甚至可以提供用於測試目的的模擬對象。關於TwitterService,DB和OAuth類也以類似的方式定義。

<?php
class SocialFeeds
{
    public $twService;

    public function __construct($twService) {
        $this->twService = $twService;
    }

    public function getSocialFeeds() {
        echo $this->twService->getTweets();
    }
}

基於設置器的注入

使用基於設置器的注入,對像是通過setter方法而不是構造函數提供的。以下是SocialFeeds類的基於設置器的依賴注入實現:

<?php
$db = new DB();
$oauth = new OAuth();
$twService = new TwitterService($db, $oauth);
$socialFeeds = new SocialFeeds($twService);
$socialFeeds->getSocialFeeds();

現在包括DB和OAuth的初始化代碼如下所示:

<?php
class SocialFeeds
{
    public $twService;

    public function getSocialFeeds() {
        echo $this->twService->getTweets();
    }

    public function setTwitterService($twService) {
        $this->twService = $twService;
    }
}

構造函數與設置器注入

選擇基於構造函數的注入還是基於設置器的注入取決於您。當需要所有依賴項才能實例化類時,基於構造函數的注入是合適的。當並非每次都需要依賴項時,基於設置器的注入是合適的。

優點

  • 構造函數 – 只需查看類的構造函數即可識別類的所有依賴項
  • 設置器 – 添加新的依賴項就像添加新的setter方法一樣簡單,不會破壞現有代碼

缺點

  • 構造函數 – 添加新的依賴項會增加構造函數的參數;需要更新整個應用程序中的現有代碼以提供新的依賴項
  • 設置器 – 我們必須手動搜索必要的依賴項,因為它們沒有在任何地方指定

了解了依賴注入和各種注入技術後,是時候看看Pimple以及它如何融入其中了。

Pimple在DI中的作用

當我們已經可以使用前面提到的技術注入依賴項時,您可能想知道為什麼需要Pimple。要回答這個問題,我們需要看看DRY原則。

不要重複自己(DRY)是軟件開發的一個原則,旨在減少各種信息的重複,這在多層架構中特別有用。 DRY原則的陳述是“每個知識片段都必須在一個系統中具有單個、明確、權威的表示”——維基百科

考慮基於構造函數的注入示例。每次我們想要SocialFeed類的對象時,我們都必須重複實例化和傳遞其依賴項的整個設置過程。根據DRY,應避免此類代碼以防止維護出現問題。 Pimple充當定義此類依賴項以避免重複的容器。讓我們來看一個簡單的例子,看看Pimple是如何工作的。

<?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}

創建Pimple的實例充當存儲依賴項的容器。它實現SPL ArrayAccess接口,因此使用它與使用數組非常相似。首先,我們定義了一個鍵,該鍵保存我們想要的某個任意類的名稱。然後,我們定義了一個閉包來返回指定類的實例,該實例充當服務。請注意,將向$c傳遞容器的實例,因此我們可以根據需要引用其他已定義的鍵;每個已定義的參數或對像都可通過$c變量在閉包中使用。現在,每當我們想要類的實例時,我們都可以引用鍵來檢索對象。讓我們將SocialFeeds示例轉換為Pimple。 Pimple官方網站上的示例顯示了基於構造函數的注入,因此在這裡我們將說明基於設置器的注入。請記住,為了使用Pimple,我們不需要修改前面定義的任何setter方法或代碼——我們只是封裝了邏輯。

<?php
class SocialFeeds
{
    public function getSocialFeeds() {
        $twService = new TwitterService();
        echo $twService->getTweets();
    }
}

DB和OAuth類都是獨立的模塊,因此我們直接在閉包內返回它們的新的實例。然後,我們使用基於設置器的注入向TwitterService類添加依賴項。我們已經將DB和OAuth類添加到容器中,因此我們可以使用$c['db']和$c['oauth']直接在函數內訪問它們。現在,依賴項作為服務封裝在容器內。每當我們想要使用不同的DB類或不同的OAuth服務時,我們只需替換容器語句中的類,一切都會完美運行。使用Pimple,您只需要在一個地方添加新的依賴項。

高級Pimple用法

在上述場景中,Pimple會在每次請求時從閉包返回每個類的新的實例。在某些情況下,我們需要使用相同的對象而無需每次都初始化新的實例,例如連接到數據庫就是一個完美的例子。 Pimple提供了使用共享對象返回相同實例的能力,這樣做需要我們通過share()方法指定閉包,如下所示:

<?php
class A
{
    public function a1() {
        $b = new B();
        $b->b1();
    }
}

此外,到目前為止,我們已經在Pimple容器中的單個位置定義了所有依賴項。但是,考慮一下我們需要具有其依賴項的服務,但配置方式與原始服務略有不同的情況。例如,假設我們需要訪問ORM來實現TwitterService類的某些功能。我們不能更改現有的閉包,因為它會強制所有現有功能使用ORM。 Pimple提供extend()方法來動態修改現有閉包,而不會影響原始實現。考慮以下代碼:

<?php
class SocialFeeds
{
    public function getSocialFeeds() {
        $twService = new TwitterService();
        echo $twService->getTweets();
    }
}

現在,我們能夠在特殊情況下使用tweet_service的不同擴展版本。第一個參數是服務的名稱,第二個參數是一個函數,該函數可以訪問對象實例和容器。實際上,extend()是動態添加依賴項以適應不同情況的強大方法,但請確保將服務的擴展版本限制在最低限度,因為它會增加重複代碼的數量。

總結

管理依賴項是Web應用程序開發中最重要和最困難的任務之一。我們可以使用構造函數和setter方法的依賴注入來有效地管理它們。但是,依賴注入本身也有一些麻煩,Pimple通過提供一個輕量級容器來以DRY的方式創建和存儲對象依賴項來解決這些問題。請隨時在下面的評論中分享您在項目中管理依賴項的經驗,以及您對Pimple作為依賴注入容器的看法。

關於使用Pimple進行依賴注入的常見問題解答 (FAQ)

什麼是Pimple,為什麼在PHP中使用它?

Pimple是一個簡單的PHP依賴注入容器,允許您管理和集中應用程序中的服務。它用於PHP,使代碼更靈活、更可重用和更易於測試。通過使用Pimple,您可以在一個地方實例化對象,然後將它們注入到應用程序的不同部分,從而減少對全局狀態的需求,並使您的代碼更易於維護和測試。

Pimple是如何工作的?

Pimple通過在容器中存儲服務定義來工作。這些定義是可以調用(函數或方法)的,它們返回服務的實例。當您從容器訪問服務時,Pimple會執行服務定義以創建服務對象。這允許您以集中方式管理服務,並在整個應用程序中共享服務。

如何安裝Pimple?

可以使用Composer(PHP的依賴項管理工具)安裝Pimple。您可以在系統上全局安裝Composer,然後通過運行命令composer require pimple/pimple在項目中引入Pimple。

如何在Pimple中定義服務?

在Pimple中,您可以通過將可調用對象分配給容器中的鍵來定義服務。可調用對象應返回服務的實例。例如,您可以像這樣為郵件發送器類定義服務:

$container['mailer'] = function ($c) { return new Mailer($c['smtp']); };

在此示例中,郵件發送器服務定義為Mailer類的新的實例,其中smtp服務作為依賴項注入。

如何在Pimple中訪問服務?

您可以使用帶有服務鍵的數組表示法來訪問Pimple中的服務。例如,您可以像這樣訪問郵件發送器服務:$mailer = $container['mailer'];。當您訪問服務時,Pimple會執行服務定義並返回服務對象。

如何在Pimple中共享服務?

默認情況下,Pimple每次訪問服務時都會返回服務的新的實例。如果您想共享服務並每次返回相同的實例,可以使用share()方法。例如,您可以像這樣共享郵件發送器服務:$container['mailer'] = $container->share(function ($c) { return new Mailer($c['smtp']); });

我可以在Pimple中擴展服務嗎?

是的,您可以使用extend()方法擴展Pimple中的服務。這允許您在定義服務後修改它。例如,您可以像這樣擴展郵件發送器服務以添加其他配置:

$container['mailer'] = $container->extend('mailer', function ($mailer, $c) { $mailer->setFrom($c['email.from']); return $mailer; });

在此示例中,setFrom()方法使用email.from服務作為參數在郵件發送器服務上調用。

如何保護Pimple中的參數?

在Pimple中,您可以使用protect()方法保護參數(不應被視為服務的參數)。這允許您在容器中存儲值,而不會將它們視為服務定義。例如,您可以像這樣保護配置值:$container['config.value'] = $container->protect(function () { return 'value'; });

如何在一個項目中使用Pimple?

您可以通過創建PimpleContainer類的新的實例並在其中定義服務來在一個項目中使用Pimple。然後,您可以在應用程序中需要的地方從容器訪問服務。這允許您以集中方式管理服務並將它們注入到應用程序的不同部分。

使用Pimple的好處是什麼?

Pimple為PHP開發提供了許多好處。它使您的代碼更靈活,因為它允許您以集中方式管理服務。它使您的代碼更易於重用,因為它允許您在整個應用程序中共享服務。它使您的代碼更易於測試,因為它允許您注入模擬服務進行測試。通過使用Pimple,您可以提高代碼質量,並使其更易於維護和測試。

以上是PHP主|用丘疹注入依賴的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
unset()和session_destroy()有什麼區別?unset()和session_destroy()有什麼區別?May 04, 2025 am 12:19 AM

Thedifferencebetweenunset()andsession_destroy()isthatunset()clearsspecificsessionvariableswhilekeepingthesessionactive,whereassession_destroy()terminatestheentiresession.1)Useunset()toremovespecificsessionvariableswithoutaffectingthesession'soveralls

在負載平衡的情況下,什麼是粘性會話(會話親和力)?在負載平衡的情況下,什麼是粘性會話(會話親和力)?May 04, 2025 am 12:16 AM

stickysessensureuserRequestSarerOutedTothesMeServerForsessionDataConsisterency.1)sessionIdentificeAssificationAssigeaSsignAssignSignSuserServerServerSustersusiseCookiesorUrlModifications.2)一致的ententRoutingDirectSsssssubsequeSssubsequeSubsequestrequestSameSameserver.3)loadBellankingDisteributesNebutesneNewuserEreNevuseRe.3)

PHP中有哪些不同的會話保存處理程序?PHP中有哪些不同的會話保存處理程序?May 04, 2025 am 12:14 AM

phpoffersvarioussessionsionsavehandlers:1)文件:默認,簡單的ButMayBottLeneckonHigh-trafficsites.2)Memcached:高性能,Idealforsforspeed-Criticalapplications.3)REDIS:redis:similartomemememememcached,withddeddeddedpassistence.4)withddeddedpassistence.4)databases:gelifforcontrati forforcontrati,有用

PHP中的會話是什麼?為什麼使用它們?PHP中的會話是什麼?為什麼使用它們?May 04, 2025 am 12:12 AM

PHP中的session是用於在服務器端保存用戶數據以在多個請求之間保持狀態的機制。具體來說,1)session通過session_start()函數啟動,並通過$_SESSION超級全局數組存儲和讀取數據;2)session數據默認存儲在服務器的臨時文件中,但可通過數據庫或內存存儲優化;3)使用session可以實現用戶登錄狀態跟踪和購物車管理等功能;4)需要注意session的安全傳輸和性能優化,以確保應用的安全性和效率。

說明PHP會話的生命週期。說明PHP會話的生命週期。May 04, 2025 am 12:04 AM

PHPsessionsstartwithsession_start(),whichgeneratesauniqueIDandcreatesaserverfile;theypersistacrossrequestsandcanbemanuallyendedwithsession_destroy().1)Sessionsbeginwhensession_start()iscalled,creatingauniqueIDandserverfile.2)Theycontinueasdataisloade

絕對會話超時有什麼區別?絕對會話超時有什麼區別?May 03, 2025 am 12:21 AM

絕對會話超時從會話創建時開始計時,閒置會話超時則從用戶無操作時開始計時。絕對會話超時適用於需要嚴格控制會話生命週期的場景,如金融應用;閒置會話超時適合希望用戶長時間保持會話活躍的應用,如社交媒體。

如果會話在服務器上不起作用,您將採取什麼步驟?如果會話在服務器上不起作用,您將採取什麼步驟?May 03, 2025 am 12:19 AM

服務器會話失效可以通過以下步驟解決:1.檢查服務器配置,確保會話設置正確。 2.驗證客戶端cookies,確認瀏覽器支持並正確發送。 3.檢查會話存儲服務,如Redis,確保其正常運行。 4.審查應用代碼,確保會話邏輯正確。通過這些步驟,可以有效診斷和修復會話問題,提升用戶體驗。

session_start()函數的意義是什麼?session_start()函數的意義是什麼?May 03, 2025 am 12:18 AM

session_start()iscucialinphpformanagingusersessions.1)ItInitiateSanewsessionifnoneexists,2)resumesanexistingsessions,and3)setsasesessionCookieforContinuityActinuityAccontinuityAcconActInityAcconActInityAcconAccRequests,EnablingApplicationsApplicationsLikeUseAppericationLikeUseAthenticationalticationaltication and PersersonalizedContentent。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具