dependency injection, zend framework and symfony container

Download Dependency Injection, Zend Framework and Symfony Container

If you can't read please download the document

Upload: diego-lewin

Post on 16-Apr-2017

3.707 views

Category:

Technology


0 download

TRANSCRIPT

Dependency Injection

Integration of Symfony DI Container to

Zend Framework

Who am I ?

Diego Lewin

Software Architect at www.fishpond.co.nz Technical Director at www.reddelacosta.com.arConsultant at www.bookfinda.com.au

What is a dependency ?

What is a dependency

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)

More dependencies

Chaining dependencies

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

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:

Dependency Injection ?
Make dependencies explicit

Inject the dependencies classes from outside through the constructor or setter methods, instead of retrived by the object itself.

.....

$cache = $boostrap->getResource('cache')$logger = $boostrap->getResource('logger')$entityManager = $boostrap->getResource('entityManager')

$productService = new ProductService($cache, $logger, $entityManager);

Injecting dependencies through the constructor:

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:

Dependency InjectionTypes

Constructor Injection: The dependencies are injected trought the constructor. Advantage is that always when created the object is ready to be used.

Setter Injection: The dependencies are injected trought setter, this can be good if a large numbers of dependencies are present.

Interface: Components implement specific containers provided by the containers in order to be configured.

Dependency Injection

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.

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)

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.

Wikipedia (http://en.wikipedia.org/wiki/Dependency_injection)

Advantages

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.

Loose Coupling.

More Testable code: Unit test, able to replace for Mocks objects.

Inject different object for different environments (different logger for dev/production).

Since the object creation is handle by a centralized component, we avoid copy paste the same code inside of different objects.

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.

DI Containers in Java

Spring

Pico

Butterfly

Java example using anotations:

@Componentpublic class SomeClass { @Autowired(required=true) public SomeClass(OtherClass bean1, OtherClass bean2) { ... }}

PHP and DI containers

Symfony Dependency Injection Written by Fabien Potencier, stand alone library http://components.symfony-project.org/ stable version

Zend Framework 2 DI Component (Beta 1)Not ready yet, but promising.

Symfony Dependency Injection

Available Formats:

- PHP

- XML

- YAML

- INI (only be able to define paramenters, no services)

Creating the Container (Boostraping)
from http://components.symfony-project.org/

require_once '/PATH/TO/sfServiceContainerAutoloader.php';sfServiceContainerAutoloader::register(); $sc = new sfServiceContainerBuilder(); $loader = new sfServiceContainerLoaderFileXml($sc);$loader->load('/somewhere/container.xml');

$sc->ipManager

From http://components.symfony-project.org/dependency-injection/trunk/book/05-Service-Description

Service Definition (XML format)
from http://components.symfony-project.org/

php://output %ipmanager.loger.file%

........

Need for Speed
from http://components.symfony-project.org/

..... $phpCointernerClassCode = $dumper->dump(array('class' => 'Container')); file_put_contents('/somewhere/container.php', $code);

Symfony DI compoment has a mechanism where optimized 'plain' php container classescan be Generated from configuration.

Once generated those containers classes can be used avoiding parsing configuration files every time.

Need for Speed
from http://components.symfony-project.org/

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).

Symfony DI - ZF Integration

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: https://github.com/diegol/Sympony-Dependency-Injection-Zend-Framwerok-Resource ):

application.ini:

[production]resources.symfonycontainer.libraryPath = LIBRARY_PATH "/Symfony/DependencyInjection/"

resources.symfonycontainer.configContainerFile = APPLICATION_PATH "/configs/services/sfServices-production.xml"

resources.symfonycontainer.dumpFile = APPLICATION_PATH "/Containers/SymfonyContainerDev.php"

resources.symfonycontainer.containerClass = "SymfonyContainerDev"

resources.symfonycontainer.generateContainerClasses = false

[development]resources.symfonycontainer.configContainerFile = APPLICATION_PATH "/configs/services/sfServices-development.xml"resources.symfonycontainer.generateContainerClasses = true

Note: Production and development in this example use diferent xml files, in this way we can use different definitions for diffrent enviroments.

Symfony DI - ZF Integration

To use it (not as tidy as Java):

$productService = $boostrap->getResource('symfonycontainer') ->getContainerBuilder() ->productService;

(byYak_Shaving)

Questions ?

Thanks..

You can find the code at: https://github.com/diegol/Sympony-Dependency-Injection-Zend-Framwerok-Resource

Muokkaa otsikon tekstimuotoa napsauttamalla

Muokkaa jsennyksen tekstimuotoa napsauttamallaToinen jsennystasoKolmas jsennystasoNeljs jsennystasoViides jsennystasoKuudes jsennystasoSeitsems jsennystasoKahdeksas jsennystasoYhdekss jsennystaso