Предотвращение циклических зависимостей между предприятиями в двух модулях

Я в настоящее время задаюсь вопросом, что хороший путь - к <сильной> сторожевой башне модули ZF2, copyable от одного проекта до другого, если у меня есть doctrine2 предприятия что ссылка друг друга.

Моя текущая ситуация - что-то вроде этого: Я сделал, чтобы предприятие <закодировало> Пользователя , от которого я хочу быть в состоянии получить доступ ко всем языкам, на которых говорит этот пользователь.

Конечно, , Язык не является компонентом Идентификация модуль, потому что я мог бы хотеть использовать его для других целей, также.

namespace Authentication\Entity;

class User {
    public function getSpokenLanguages();
}

И:

namespace Application\Entity;

class Language {
    public function getUsersWhoSpeakThisLanguage();
}

Проблема, я хочу, чтобы мой Идентификация модуль был полностью независим от определенного для проекта модуля Применение .

Есть ли хороший способ не допустить эти отношения в мои предприятия или возможно ввести их от Применение модуль? Возможно, также UserService Применение модуль) предоставление мне языки Язык [] для определенного Пользователь был бы хорошей идеей? Я мог назвать его как это:

$userService->getUsersLanguages($user);

Я думаю, особенно инъекцией могло бы быть ZF2-решение, но я понятия не имею, как можно было расширить предприятия Doctrine2 как этот от другого модуля.

1
nl ja de

1 ответы

Я думаю, что вы говорите с большим количеством семантической проблемы, чем одно характерное для ZF2. Читая ваш вопрос, я думаю, что ваш язык становится большим количеством управляемого слоя, который можно легко облегчить с фабриками и DI - к счастью, у ZF2 есть все правильные инструменты. Рассмотрите что-то вроде этого как потенциальный проект для решения:

Создайте LanguageAbstractFactory :

namespace Your\Namespace;

use Zend\ServiceManager\AbstractFactoryInterface,
    Zend\ServiceManager\ServiceLocatorInterface;

class LanguageAbstractFactory implements AbstractFactoryInterface
{
    /**
     * Determine if we can create a service with name
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @param                         $name
     * @param                         $requestedName
     * @return bool
     */
    public function canCreateServiceWithName( ServiceLocatorInterface $serviceLocator, $name, $requestedName )
    {
        return stristr( $requestedName, 'Namespace\Language' ) !== false;
    }


    public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
    {
        $filter = new $requestedName();
        $filter->setServiceLocator( $locator );
        return $filter;
    }

}

Затем создайте свои языки в том же самом пространстве имен, как подклассы Языка, то орудие ServiceLocatorAwareInterface (чтобы дать вам доступ к базе данных в будущем и такой). Кодекс на фабрике выше вводит сервисный локатор (и это - то, где вы щипаете его, чтобы ввести другое совершенство, чтобы удовлетворить вашу языковую архитектуру):

namespace Your\Namespace;

use Zend\ServiceManager\ServiceLocatorAwareInterface,
    Zend\ServiceManager\ServiceLocatorInterface;


class Language implements ServiceLocatorAwareInterface
{

    protected $serviceLocator;


    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

   //... other things your factory knows, that this class may not go here
}

<Сильное> Языковое внедрение могло бы тогда быть похожим:

namespace Your\Namespace\Language;

class English extends \Your\Namespace\Language
{

    public function getUsersWhoSpeakThisLanguage()
    {
        $sm = $this->getServiceManager();
       //get your entities or w/e using the SM
    }
}

Соедините фабрику, щипнув Module.php вашего модуля в getServiceConfig:

государственная функция getServiceConfig() { возвращаемый массив (

        'abstract_factories' => array(
           //this one generates all of the mass email filters
            'Your\Namespace\LanguageAbstractFactory',
        ),

    );
}

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

$sm->getServiceManager()->get( '\Your\Namespace\Language\English' );

Из-за конфигурации, и что Фабрика может удовлетворить запросу, ваша фабрика будет автоформировать английский случай с любой логикой, которую вы встраиваете в него очень портативным способом.

Где это - своего рода краткая информация о Фабриках - если вы подстраиваете интерфейсный класс, который обслуживание может использовать, чтобы говорить с вашими пользовательскими классами, можно инвертировать контроль к Языковому обслуживанию от Пользователя. Создание вашего Пользователя осуществить LanguageAware (например), который содержит классы, которые может использовать Языковое обслуживание, должно быть несколькими шагами далеко.

Надежда это помогает. Есть, вероятно, 15 способов освежевать эту кошку; этот подход - тот, который я раньше решал подобные проблемы, например, та из "Фильтрации" данных. Фильтр, может отфильтровать информацию, и информация может быть фильтрована фильтром.

Удачи!

1
добавлено
У меня есть проблемы понять, как фабрика становится названной, когда я называю новый случай языка от сервисного локатора. Я не вижу правила для него. И большая проблема: Я не вижу, как это помогает мне избавление от пользователя-> прикладная зависимость. Я все еще твердое закодировал метод getStuffFromOtherModule() , не так ли? Угадайте, что это - потому что я полностью не используюсь, чтобы работать с DI и ServiceLocators, все же.
добавлено автор Aufziehvogel, источник
Проверка @Aufziehvogel blog.evan.pro/…
добавлено автор Ocramius, источник