PHP Dependency Injection

前端 未结 4 1330
一个人的身影
一个人的身影 2020-11-29 05:42

I\'m trying to get my head around Dependency Injection and I understand it, for the most part.

However, say if, for some reason, one of my classes was dependent on s

4条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-29 06:20

    I've wrote an article about this problem. The ideea is to use a combination of abstract factory and dependency injection to achieve transparent dependency resolving of (possible nested) dependencies. I will copy/paste here the main code snippets:

    namespace Gica\Interfaces\Dependency;
    
    interface AbstractFactory
    {
        public function createObject($objectClass, $constructorArguments = []);
    }
    

    The abstract factory implementation is:

    namespace Gica\Dependency;
    
    class AbstractFactory implements \Gica\Interfaces\Dependency\AbstractFactory, \Gica\Interfaces\Dependency\WithDependencyInjector
    {
        use WithDependencyInjector;
    
        /**
         * @param string $objectClass
         * @param array $constructorArguments
         * @return object instanceof $class
         */
        public function createObject($objectClass, $constructorArguments =     [])
        {
            $instance = new $objectClass(...$constructorArguments);
    
            $this->getDependencyInjector()->resolveDependencies($instance);
    
            return $instance;
        }
    }
    

    The dependency injector is this: namespace Gica\Dependency;

    class DependencyInjector implements \Gica\Interfaces\Dependency\DependencyInjector
    {
        use \Gica\Traits\WithDependencyContainer;
    
        public function resolveDependencies($instance)
        {
            $sm = $this->getDependencyInjectionContainer();
    
            if ($instance instanceof \Gica\Interfaces\WithAuthenticator) {
                $instance->setAuthenticator($sm->get(\Gica\Interfaces\Authentication\Authenticator::class));
            }
            if ($instance instanceof \Gica\Interfaces\WithPdo) {
                $instance->setPdo($sm->get(\Gica\SqlQuery\Connection::class));
            }
    
            if ($instance instanceof \Gica\Interfaces\Dependency\WithAbstractFactory) {
                $instance->setAbstractFactory($sm->get(\Gica\Interfaces\Dependency\AbstractFactory::class));
            }
            //... all the dependency declaring interfaces go below
        }
    }
    

    The dependency container is the standard one. The client code could look something like this:

    $abstractFactory = $container->get(\Gica\Interfaces\Dependency\AbstractFactory::class);
    
    $someHelper = $abstractFactory->createObject(\Web\Helper\SomeHelper::class);
    
    echo $someHelper->helpAction();
    

    Notice that dependencies are hidden, and we can focus on the main bussiness. My client code doesn't care or know that $someHelper need an Authenticator or that helpAction need an SomeObject to do its work;

    In the background a lot of things happen, a lot of dependencies are detected, resolved and injected. Notice that I don't use the new operator to create $someObject. The responsability of actual creation of the object is passed to the AbstractFactory

    P.S. Gica is my nickname :)

提交回复
热议问题