簡體   English   中英

PHP如何防止疙瘩DIC導致循環依賴無限循環

[英]PHP How to prevent pimple DIC causing infinite loop on a circular dependency

在此示例中,我將classAclassAclassB容器一起使用。

他們都相互依賴。 然而,當用 pimple DIC 設置它時,下面的代碼會導致無限循環......

必須有一種方法可以在 pimple 中做到這一點,但我在文檔中看不到它......任何想法如何防止無限循環?

// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();

use Classes\ClassA;
$container['ClassA'] = function ($c) {
  return new ClassA($c['ClassB']);
};

use Classes\ClassB;
$container['ClassB'] = function ($c) {
  return new ClassB($c['ClassA']);
};

嚴格來說,你的問題與青春痘無關。

你只是有一個循環構造函數依賴,沒有辦法修復它們。 A需要B需要A需要B...

問題是,通常,兩個相互依賴的類沒有多大意義。 但是在這種情況發生的極少數情況下,兩者之一應該是較輕的依賴項,您可以在實例化之后通過 setter 或類似機制注入對象。

通過傳遞容器並在ClassB內部實例化,您隱藏了您的依賴項,這超出了擁有依賴項注入容器的目的。 現在ClassB取決於Container ,而不是ClassA ,這是您首先想要的。

而不是這樣做,只需將方法setA(Class A $a)到您的ClassB

然后,您通過調用$b->setA($container['ClassA']);注入您的依賴項$b->setA($container['ClassA']); 當您真正需要它時,而不是在 DI 容器上。 正如 Adam指出的那樣,您甚至可以通過擴展您的服務並在服務定義上使用 setter 來在您的容器中進行 setter 注入。

但再次重申,您的主要問題是有一個循環依賴 再想一想。 可能表明您的設計可以進行一些改進。

@yivi 首先在他們關於循環引用有效性的回答中做出了有效的觀察。 所以我真的認為你應該在這里評估你的設計。 您可能正在治療症狀,而不是根本問題。 盡管考慮到您的通用示例代碼(這是解決手頭問題的好代碼,說),但我們不可能對此發表評論。 如果您認為值得的話,也許可以對您的設計提出一個新問題? 在這里或在Code Review 上,也許?

如果您控制ClassAClassB的設計,那么處理此類事情的規定方法是使用 setter 注入,而不是構造函數注入。

這應該有效:

// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();

use Classes\ClassA;
$container['ClassA'] = function ($c) {
  return new ClassA();
};

use Classes\ClassB;
$container['ClassB'] = function ($c) {
  return new ClassB();
};


$container->extend('ClassA', function ($instanceOfA, $container) {
    $instanceOfA->setB($container['ClassB']);

    return $instanceOfA;
});

$container->extend('ClassB', function ($instanceOfB, $container) {
    $instanceOfB->setA($container['ClassA']);

    return $instanceOfB;
});

(未經測試,可能包含拼寫錯誤,但這是一般要點)

請注意原始構造函數如何不再采用依賴項,將其插入留給特定的 setter。 這允許您在容器中創建服務,然后使用extend然后調用相關的設置器在此之后插入依賴項。

這是在文檔中: Modifying Services after Definition

// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();

use Classes\ClassA;
$container['ClassA'] = function ($c) {
  return new ClassA($c['ClassB']);
};

use Classes\ClassB;
$container['ClassB'] = function ($c) {
  return new ClassB($c);
};

不是從 classB 實例化 ClassA,而是將容器傳遞給 ClassB。 然后當你在 ClassB 中需要 ClassA 時,你可以使用你傳遞給它的容器來啟動/獲取 ClassA 的實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM