Dependency Injection, Zend Framework and Symfony Container


Published on

Introduction of Dependency Injection pattern, and integration of 'Symfony Injection' component and 'Zend Framework'.

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Dependency Injection, Zend Framework and Symfony Container

  1. 1. Dependency Injection Integration of Symfony DI Container to Zend Framework
  2. 2. Who am I ? <ul><li>Diego Lewin
  3. 3. Software Architect at
  4. 4. Technical Director at
  5. 5. Consultant at </li></ul>
  6. 6. <ul><li>What is a dependency ? </li></ul><ul><li>What is a dependency </li></ul>Product Service class Cache class Loging class EntityManager class 'Object A' dependends on 'Object B' if 'Object A' needs 'Object B' in order to execute correctly. (Jakob Jenkov)
  7. 7. More dependencies <ul><li>Chaining dependencies </li></ul>Product Service class Cache class Loging class EntityManager class DB Writer class Frontend class Backend class Log Writer class As the size of the applications grows, the amount and complexity of dependencies grows as well
  8. 8. Hardcoded Dependencies Make dependencies explicit class ProductService { ... public function __constructor() { $boostrap = Zend_Controller_Front::getInstance()->getParam('bootstrap'); $this->_cache = $boostrap->getResource('cache'); $this->_logger = $boostrap->getResource('logger'); $this->_entityManager = $boostrap->getResource('entityManager'); } } We have hardcoded dependencies when, the class set its dependencies by itself:
  9. 9. Dependency Injection ? Make dependencies explicit <ul><li>Inject the dependencies classes from outside through the constructor or setter methods, instead of retrived by the object itself. </li></ul>..... $cache = $boostrap->getResource('cache') $logger = $boostrap->getResource('logger') $entityManager = $boostrap->getResource('entityManager') $productService = new ProductService( $cache, $logger, $entityManager ); Injecting dependencies through the constructor:
  10. 10. New Code... Make dependencies explicit class ProductService { ... public function __constructor($cache, $logger, $entityManager) { $this->_cache = $cache; $this->_logger = $logger; $this->_entityManager = $entityManager; } } Injecting dependencies through the constructor:
  11. 11. Dependency InjectionTypes <ul><li>Constructor Injection: The dependencies are injected trought the constructor. Advantage is that always when created the object is ready to be used.
  12. 12. Setter Injection: The dependencies are injected trought setter, this can be good if a large numbers of dependencies are present.
  13. 13. Interface: Components implement specific containers provided by the containers in order to be configured. </li></ul>
  14. 14. Dependency Injection <ul><li>Without dependency injection, a consumer component that needs a particular service in order to accomplish a task must create an instance of a class that concretely implements the dependency interface.
  15. 15. When using dependency injection, a consumer component specifies the service contract by interface, and the injector component selects an implementation on behalf of the dependent component. (inversion of control)
  16. 16. In its simplest implementation, code that creates a dependent object supplies dependencies to that object via constructor arguments or by setting properties on the object.
  17. 17. Wikipedia ( </li></ul>
  18. 18. Advantages <ul><li>Make dependencies explicit: Makes it clear which are the dependencies, we don't have to go trought all the code to see which are the dependencies.
  19. 19. Loose Coupling.
  20. 20. More Testable code: Unit test, able to replace for Mocks objects.
  21. 21. Inject different object for different environments (different logger for dev/production).
  22. 22. Since the object creation is handle by a centralized component, we avoid copy paste the same code inside of different objects. </li></ul>
  23. 23. Dependency Injection Container DI container The Container knows: - How the create new objects. - Classes Dependencies. Cache Logger EManager ProductService Cache Logger Event Manager An object and its dependencies can be created and initialized by a ”Dependency - Injection Container”.
  24. 24. DI Containers in Java <ul><li>Spring
  25. 25. Pico
  26. 26. Butterfly </li></ul>Java example using anotations: @Component public class SomeClass { @Autowired(required=true) public SomeClass(OtherClass bean1, OtherClass bean2) { ... } }
  27. 27. PHP and DI containers <ul><li>Symfony Dependency Injection
  28. 28. Written by Fabien Potencier, stand alone library stable version
  29. 29. Zend Framework 2 DI Component (Beta 1)
  30. 30. Not ready yet, but promising. </li></ul>
  31. 31. <ul>Symfony Dependency Injection </ul><ul><li>Available Formats: </li></ul>- PHP - XML - YAML - INI (only be able to define paramenters, no services)
  32. 32. Creating the Container (Boostraping) from require_once '/PATH/TO/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register(); $sc = new sfServiceContainerBuilder(); $loader = new sfServiceContainerLoaderFileXml($sc); $loader->load('/somewhere/container.xml'); $sc->ipManager From
  33. 33. Service Definition (XML format) from <service id=&quot;ipManager&quot; class=&quot;MyLib _Gearman_Client_Competitor_IpManager&quot; > <argument type=&quot;service&quot; id=&quot;documentManager&quot;/> <argument type=&quot;service&quot; id=&quot;gearmanClient&quot;/> <argument type=&quot;service&quot; id=&quot;ipmanager.logger&quot;/> </service> <service id=&quot;ipmanager.logger&quot; class=&quot;MyLib_Log&quot; constructor=&quot;getInstance&quot;> <call method=&quot;addWriter&quot;> <argument type=&quot;service&quot;> <service class=&quot;Zend_Log_Writer_Stream&quot;> <argument>php://output</argument> </service> </argument> </call> <call method=&quot;addWriter&quot;> <argument type=&quot;service&quot;> <service class=&quot;Zend_Log_Writer_Stream&quot;> <argument>%ipmanager.loger.file%</argument> </service> </argument> </call> </service> .... ....
  34. 34. Need for Speed from ..... $phpCointernerClassCode = $dumper->dump(array('class' => 'Container')); file_put_contents('/somewhere/container.php', $code); Symfony DI compoment has a mechanism where optimized 'plain' php container classes can be Generated from configuration. Once generated those containers classes can be used avoiding parsing configuration files every time.
  35. 35. Need for Speed from class SymfonyContainerDev extends sfServiceContainer { protected function getLogerService() { if (isset($this->shared['loger'])) return $this->shared['loger']; $instance = call_user_func(array('MyLib_Log', 'getResource')); return $this->shared['loger'] = $instance; } protected function getIpManagerService() { if (isset($this->shared['ipManager'])) return $this->shared['ipManager']; $instance = new Fishpond_Gearman_Client_Competitor_IpManager( $this->getService('documentManager'), $this->getService('gearmanClient'), $this->getService('ipmanager.logger')); return $this->shared['ipManager'] = $instance; } ...... ..... } The Container Builder use the configuration to create a php container class that is able to create an inject dependencies. The Container class created it is optimized for speed and don't have any overhead (parsing configuration files, etc).
  36. 36. Symfony DI - ZF Integration <ul>Custom_Resource_Symfonycontainer I worte a 'Custom Zend Application Resource' ,to define diferent services we use the container configuration files described in the documentation, and we use the 'application.ini' only to configure the resource itself. You can find the code at: ): application.ini: [production] resources.symfonycontainer.libraryPath = LIBRARY_PATH &quot;/Symfony/DependencyInjection/&quot; resources.symfonycontainer.configContainerFile = APPLICATION_PATH &quot;/configs/services/sfServices-production.xml&quot; resources.symfonycontainer.dumpFile = APPLICATION_PATH &quot;/Containers/SymfonyContainerDev.php&quot; resources.symfonycontainer.containerClass = &quot;SymfonyContainerDev&quot; resources.symfonycontainer.generateContainerClasses = false [development] resources.symfonycontainer.configContainerFile = APPLICATION_PATH &quot;/configs/services/sfServices-development.xml&quot; <li>resources.symfonycontainer.generateContainerClasses = true
  37. 37. Note: Production and development in this example use diferent xml files, in this way we can use different definitions for diffrent enviroments. </li></ul>
  38. 38. Symfony DI - ZF Integration <ul>To use it (not as tidy as Java): $productService = $boostrap->getResource('symfonycontainer') ->getContainerBuilder() ->productService; </ul>
  39. 39. (byYak_Shaving)
  40. 40. Questions ? Thanks.. <ul>You can find the code at: </ul>