Помощь с внедрением зависимостей в приложении MVC

Приложение Zend Framework/Doctrine 2.:

/app
    /modules
        /blog
            /controllers
                /BlogController.php
            /domain
                /entities
                /services
                    /PostService.php
                /repositories

PostService отвечает за базовые операции CRUD, работая непосредственно с сущностями и EntityManager, чтобы абстрагировать бизнес-логику и логику постоянства от моих контроллеров.

Если возможно, я хотел бы сохранить свои услуги в качестве POPO. Как лучше всего получить доступ/внедрить EntityManager в мой класс обслуживания? Я новичок в DI, поэтому этот вопрос. EntityManager доступен как загрузочный ресурс в моих контроллерах.

Должен ли я просто написать абстрактный класс для служб для доступа к EntityManager? Должен ли я написать класс для создания экземпляров моих служб, внедряя EntityManager через конструктор/сеттер?... который будет включать интерфейс для моих служб. Должен ли я использовать структуру DI? Если да, то какой и как?

Или есть другой, лучший способ сделать это?

Я читал об инъекциях зависимостей, но до сих пор не полностью понял это в этом контексте.


Обновление (12 января 2011 г.)

Итак, это мое текущее рабочее решение: у меня есть помощник действия под названием Resource, это помощник для извлечения ресурсов из начальной загрузки, или вы можете добавить к нему ресурсы вручную: http://pastie.org/1450851

$this->_helper->Resource('em'); // get EntityManager

Может ли кто-нибудь дать некоторое представление о влиянии на производительность локального хранения ресурсов начальной загрузки в вспомогательном классе? Я слишком много делаю?
ЗАДАЧА: Рефакторинг resourcesMap вне класса.

И у меня есть помощник по загрузке служб: http://pastie.org/1450855
TODO: Добавить проверяет перед попыткой загрузить службу.

Покритикуйте вышеизложенное :)


comment
К вашему сведению, мне нравится структура домена в каждом модуле. Однако как вы представляете себе взаимодействие межмодульных сущностей? Пример: у вас также есть модуль форума и вы хотите поделиться общей сущностью пользователя. Где живет определение пользователя и есть ли у каждого модуля собственная реализация?   -  person jsuggs    schedule 12.01.2011
comment
Я полагаю, что я бы создал модуль учетной записи, и сущность пользователя будет жить там.   -  person Cobby    schedule 12.01.2011


Ответы (2)


Чтобы отделить мой сервисный уровень от остального приложения, я часто полагаюсь на свои контроллеры для обработки внедрения. Мне еще предстоит разобрать и использовать контейнер DI, но инжектор ресурсов описал здесь идеально подходит для передачи EntityManager вокруг моего приложения.

EntityManager создается в начальной загрузке как ресурс, и ActionHelper добавит его в контроллер, если контроллер запрашивает его. Затем я передам его служебным объектам либо с помощью внедрения конструктора, либо внедрения сеттера.

class MyController extends Zend_Action_Controller
{
    // A little different from O'Phinney's implementation. I'm adding
    // the resource named 'entitymanager' as the public property $em.
    public $dependencies = array(
      'entitymanager' => 'em'
    );

    public function myAction()
    {
       $service = new MyService($this->em);
       // or...
       $service = new MyService();
       $service->setEntityManager($em);
    } 
}

Я также использую интерфейс под названием IHasEntityManager.

Если вы не хотите, чтобы ваш контроллер отвечал за создание объектов службы, вы можете заглянуть в контейнер внедрения зависимостей, например Внедрение зависимостей Symfony.

person Bryan M.    schedule 06.01.2011
comment
Не могли бы вы рассказать мне об этом свойстве $dependencies? - person Cobby; 07.01.2011
comment
Извините, пропустил ссылку на пост О'Финни. - person Cobby; 07.01.2011
comment
Если бы вы сделали что-то похожее на это, но объединили это в помощник действий. - person Cobby; 11.01.2011
comment
Если бы EntityManager внедрялся в каждую службу через их конструкторы, нарушило бы это принцип DRY? - person Cobby; 12.01.2011
comment
@Bryan, пожалуйста, взгляните на мое обновление в исходном посте и скажите, что вы думаете? - person Cobby; 12.01.2011
comment
Мне это кажется нормальным. Помощник для сокращения многоэтапного процесса получения чего-либо из начальной загрузки кажется мне хорошей идеей. То же самое относится и к объекту, который возвращает правильно настроенный сервис. - person Bryan M.; 14.01.2011

У Бена Шолцена (@DASPRiD) есть пример собственной псевдоструктуры DI в исходный код для своего блога. Он использует настраиваемые преобразователи для своего сохранения, которые он передает каждой службе при создании экземпляра службы. Но кажется, что было бы легко модифицировать вместо этого экземпляр Doctrine2 EntityManager.

person David Weinraub    schedule 06.01.2011