another_dream
@another_dream
Backend-разработчик, Laravel/ZF2/Yii2

Как решить проблему «Circular dependency» в Zend 2 или вообще грамотно организовать внедрение зависимостей?

Имеется 2 сервиса (TableGateway) и фабрики к ним: Day и DaySet.

Day:

- id
- date
- dayset
DaySet:

- id
- title


Day связан с DaySet по полю dayset.
Оба TableGateway собираются фабрикой (DayTableFactory и DaySetTableFactory).

Так как Day относится к DaySet - в фабрике DayTableFactory через сервис-менеджер получаю экземпляр DaySetTable:
DayTableFactory
public function __invoke(ServiceLocatorInterface $serviceLocator) {
    // ...
    $daySetTable = $serviceLocator->get(DaySetTable::class);

    return DayTable(..., $daySetTable);
}



В DayTable имеется метод, который "мэпает" объект Day, заполняя поле dayset объектом DaySet:
DayTable::populate($item)
$daySetId = $item->getDayset()
/** @var DaySet $daySetObject */
$daySetObject = $this->daySetTable->get($daySetId);
$item->setDayset($daySetObject);



Необходимо подобное реализовать в DaySetTable, дабы этот тэйбл-гейт сервис мог мэпать свои объекты (DaySet) и наполнять, например, свойство DaySet::days (@var Day[]|array $days).

Если в фабрике DaySetTable тянуть из сервис-менеджера (ServiceLocator) инстанс DayTable - Circular Dependency error, оно и понятно.

Передавать ServiceLocator (используя тот же ServiceLocatorAwareTrait) в сервис DaySetTable - не самый разумный шаг, учитывая, что данный подход уже deprecated в ZF3.

Вопрос - как разрешить цикличную зависимость (DaySetTable <-> DayTable) не сообщая сервису (DaySet) о сервис-контейнере?
  • Вопрос задан
  • 223 просмотра
Пригласить эксперта
Ответы на вопрос 2
@novrm
Поставьте ограничение на количество циклов.
В классе пропишите некую переменную, которая будет уменьшатся до определенного значения при каждой итерации.
Ответ написан
Комментировать
@Fortop
Tech/Team lead
Проблема циклической зависимости решается инициализацией одной из зависимостей при первом обращении, а не при инстанцировании.

class a {}

class b {
    public function _construct($locator){}
    public function someOperation() {
        $this->dependency = $this->dependency ??  $this->locator->get(a::class);
        //..... 
    } 
}


При этом класс "a" может по-прежнему получать зависимость через конструктор без инъекции локатора
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы