Инъекция зависимостей PHP и контейнер зависимостей с диспетчером событий - PullRequest
3 голосов
/ 02 ноября 2011

Прочитав эту замечательную статью о внедрении зависимостей: http://miller.limethinking.co.uk/2011/07/07/dependency-injection-moving-from-basics-to-container/

Я понял, что моя небольшая инфраструктура по большей части уже использует контейнер для инъекций Denedency.

У меня есть класс Appс управлением созданием всех сервисов Database, Config, Session, и это может создавать различные классы.

Но я понял, что одна часть вызывает проблемы, я передаю диспетчер событий многим базовым классам в моей среде, но каждый из этих классов использует диспетчер, например:

$this->dispatcher->fire(new FB_Event('FB.Database.Model.beforeUpdate', $this, array('pk' => $pk, 'row' => $row)));

Итаккак вы видите, я использую new , поэтому я не могу полностью выполнить модульные тесты своих классов.Я не хочу передавать свой контейнер приложения всем приложениям, потому что отладка - это кошмар, так как приложение содержит экземпляры базы данных, сеанса и множества служб, которые не нужны другим классам.

Каков наилучший способ решения этой проблемы, поскольку я не могу передать FB_Event через внедрение зависимостей, поскольку та же самая функция обычно запускает событие 2:

public function delete($pk) {
    $e = $this->dispatcher->fire(new FB_Event('FB.Database.Model.beforeDelete', $this, array('pk' => $pk)));
    $pk = $e->params['pk'];
    if ($e->preventDefault()) {
        return false;
    }

    $this->requirePK();
    list ( $where, $params ) = $this->pkParts(null, $pk);
    $sql = "DELETE FROM {$this->name} WHERE $where";
    $stm = $this->db->execute($sql, $params);

    $this->dispatcher->fire(new FB_Event('FB.Database.Model.afterDelete', $this, array('pk' => $pk)));
    return!(bool) $stm->errorCode();
}

Одним из моих решений является добавление новой функции в диспетчер с именемfireEvent, который позаботится о создании нового FB_Event, который удалит соединение повсюду.Но добавит связь между Диспетчером и Событием, которая менее плоха.

public function fireEvent($name, $target, $params = array()) {
    return $this->fire(new FB_Event($name, $target, $params = array()));
}

Не могли бы вы создать какой-нибудь EventFactory в контейнере и передать его Диспетчеру?Является ли это излишним, чтобы удалить зависимость от небольшого объекта, такого как Event?

Спасибо за ваш совет

Ответы [ 2 ]

1 голос
/ 02 ноября 2011

Я действительно думаю, что предложенное вами решение - лучший ответ. Вы правы в том, что следует избегать создания экземпляра FB_Event в коде, поскольку это затрудняет (-er) тестирование и сопряжение вашего кода. Да, в вашем методе fireEvent есть связь между классом Dispatcher и классом Event, но Dispatcher должен знать о событиях, так как он отправляет их. Да, связывания следует избегать, но некоторые классы иногда должны знать о других классах; сцепления не всегда можно избежать. Хорошая вещь в вашем методе fireEvent заключается в том, что он представляет собой шов и, следовательно, может использоваться для разбивки кода в будущем.

1 голос
/ 02 ноября 2011

Каков наилучший способ решения этой проблемы, поскольку я не могу передать FB_Event через внедрение зависимостей, так как эта же функция обычно запускает событие 2:

Вы можете обойти эту проблему, используясеттеры в вашем FB_Event классе.Например, передайте экземпляр FB_Event (DI) соответствующему классу и используйте его как:

public function delete($pk) {

    $this->fb_event->setName('FB.Database.Model.beforeDelete');     
    $this->fb_event->setTarget($this);
    $this->fb_event->setParams(array('pk' => $pk));

    $e = $this->dispatcher->fire($this->fb_event);
    $pk = $e->params['pk'];
    if ($e->preventDefault()) {
        return false;
    }

    $this->requirePK();
    list ( $where, $params ) = $this->pkParts(null, $pk);
    $sql = "DELETE FROM {$this->name} WHERE $where";
    $stm = $this->db->execute($sql, $params);

    $this->fb_event->reset();
    $this->fb_event->setName('FB.Database.Model.afterDelete'); 
    $this->fb_event->setTarget($this);
    $this->fb_event->setParams(array('pk' => $pk));    

    $this->dispatcher->fire($this->fb_event);
    return!(bool) $stm->errorCode();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...