【问题标题】:new child of parent's constructor with dependency not working具有依赖项的父构造函数的新子代不起作用
【发布时间】:2014-07-08 10:25:18
【问题描述】:

我对通过工厂实例化的 A 类和 B 类扩展 A 类有疑问。

这里有一些示例代码:

class ClassAFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $one= $serviceLocator->get('doctrine.entitymanager.one');
        $two= $serviceLocator->get('doctrine.entitymanager.two');
        $three= $serviceLocator->get('Application\Service\three');
        return new ClassA($one, $two, $three);
    }
}

class ClassA implements ServiceLocatorAwareInterface
{
    use ServiceLocatorAwareTrait;

    private $one;
    private $two;
    private $three;

    public function __construct(ObjectManager $one, ObjectManager $two, Three $three)
    {
        $this->one= $one;
        $this->two= $two;
        $this->three= $three;
    }
}

class ClassB extends ClassA
{
    // Some usefull code
}

如何在不传递依赖关系的情况下调用 B 类,如何检索工厂完成的 A 类实例:new ClassB(); ?

【问题讨论】:

    标签: php dependency-injection zend-framework2 factory


    【解决方案1】:

    你不能直接这样做。您也可以ClassB 创建一个服务工厂,但这涉及到代码重复:

    class ClassBFactory implements FactoryInterface
    {
        public function createService(ServiceLocatorInterface $serviceLocator)
        {
            $one   = $serviceLocator->get('doctrine.entitymanager.one');
            $two   = $serviceLocator->get('doctrine.entitymanager.two');
            $three = $serviceLocator->get('Application\Service\three');
            return new ClassB($one, $two, $three);
        }
    }
    

    但是,您的课程ClassA(因此ClassB)已经知道服务定位器,因此您可以延迟加载您的实体管理器;这样,您根本不需要服务工厂:

    class ClassA implements ServiceLocatorAwareInterface
    {
        use ServiceLocatorAwareTrait;
    
        private $one;
        private $two;
        private $three;
    
        private function getOne()
        {
            if (!$this->one) {
                $this->one = $this->getServiceLocator()
                                  ->get('doctrine.entitymanager.one');
            }
    
            return $this->one;
        }
    
        private function getTwo()
        {
            if (!$this->two) {
                $this->two = $this->getServiceLocator()
                                  ->get('doctrine.entitymanager.two');
            }
    
            return $this->two;
        }
    
        public function __construct(Three $three)
        {
            $this->three = $three;
        }
    }
    
    class ClassB extends ClassA
    {
        // Some usefull code
    }
    

    只需更新ClassA 中的代码,即可使用$this->getOne()$this->getTwo() 而不是$this->one$this->two 访问您的实体管理器。

    之后,您可以像其他人一样访问ClassA & ClassB

    $a = $serviceLocator->get('Namespace\...\ClassA');
    $b = $serviceLocator->get('Namespace\...\ClassB');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多