How to use dependency injection in Zend Framework?

前端 未结 5 771
攒了一身酷
攒了一身酷 2021-02-02 14:52

Currently I am trying to learn the Zend Framework and therefore I bought the book \"Zend Framework in Action\".

In chapter 3, a basic model and controller is introduced

5条回答
  •  滥情空心
    2021-02-02 15:37

    Ok, this is how I did it:

    As IoC Framework I used this component of the symfony framework (but I didnt download the latest version, I used an older one I used on projects before... keep that in mind!). I added its classes under /library/ioc/lib/.

    I added these init function in my Bootstrap.php in order to register the autoloader of the IoC framework:

    protected function _initIocFrameworkAutoloader()
    {
        require_once(APPLICATION_PATH . '/../library/Ioc/lib/sfServiceContainerAutoloader.php');
    
        sfServiceContainerAutoloader::register();
    }
    

    Next, I made some settings in application.ini which set the path to the wiring xml and allow to disable automatic dependency injection e. g. in unit tests:

    ioc.controllers.wiringXml = APPLICATION_PATH "/objectconfiguration/controllers.xml"
    ioc.controllers.enableIoc = 1
    

    Then, I created a custom builder class, which extends sfServiceContainerBuilder and put it under /library/MyStuff/Ioc/Builder.php. In this test project I keep all my classes under /library/MyStuff/.

    class MyStuff_Ioc_Builder extends sfServiceContainerBuilder
    {
      public function initializeServiceInstance($service)
      {
          $serviceClass = get_class($service);
          $definition = $this->getServiceDefinition($serviceClass);
    
    
        foreach ($definition->getMethodCalls() as $call)
        {
          call_user_func_array(array($service, $call[0]), $this->resolveServices($this->resolveValue($call[1])));
        }
    
        if ($callable = $definition->getConfigurator())
        {
          if (is_array($callable) && is_object($callable[0]) && $callable[0] instanceof sfServiceReference)
          {
            $callable[0] = $this->getService((string) $callable[0]);
          }
          elseif (is_array($callable))
          {
            $callable[0] = $this->resolveValue($callable[0]);
          }
    
          if (!is_callable($callable))
          {
            throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service)));
          }
    
          call_user_func($callable, $service);
        }
    
      }
    }
    

    Last, I created a custom controller class in /library/MyStuff/Controller.php which all my controllers inherit from:

    class MyStuff_Controller extends Zend_Controller_Action {
        /**
         * @override
         */
        public function dispatch($action)
        {
            // NOTE: the application settings have to be saved 
            // in the registry with key "config"
            $config = Zend_Registry::get('config');
    
            if($config['ioc']['controllers']['enableIoc'])
            {
                $sc = new MyStuff_Ioc_Builder();
    
                $loader = new sfServiceContainerLoaderFileXml($sc);
                $loader->load($config['ioc']['controllers']['wiringXml']);
    
                $sc->initializeServiceInstance($this);
            }
    
            parent::dispatch($action);
        }
    }
    

    What this basically does is using the IoC Framework in order to initialize the already created controller instance ($this). Simple tests I did seemed to do what I want... let´s see how this performs in real life situations. ;)

    It´s still monkey patching somehow, but the Zend Framework doesn´t seem to provide a hook where I can create the controller instance with a custom controller factory, so this is the best I came up with...

提交回复
热议问题