120

Real World Dependency Injection - phpugffm13

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Real World Dependency Injection - phpugffm13
Page 2: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Über mich

Stephan Hochdörfer

Head of IT der bitExpert AG, Mannheim

PHP`ler seit 1999

[email protected]

@shochdoerfer

Page 3: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Was sind Dependencies?

Page 4: Real World Dependency Injection - phpugffm13

Was sind Dependencies?

Applikation

Framework Bibliotheken

Real World Dependency Injection

Page 5: Real World Dependency Injection - phpugffm13

Was sind Dependencies?

Controller

Service / Model

Datastore(s)

UtilsPHP Extensions

Real World Dependency Injection

Page 6: Real World Dependency Injection - phpugffm13

Sind Dependencies schlecht?

Real World Dependency Injection

Page 7: Real World Dependency Injection - phpugffm13

Sind Dependencies schlecht?

Dependencies sind nicht schlecht!

Real World Dependency Injection

Page 8: Real World Dependency Injection - phpugffm13

Sind Dependencies schlecht?

Nützlich und sinnvoll!

Real World Dependency Injection

Page 9: Real World Dependency Injection - phpugffm13

Sind Dependencies schlecht?

Fixe Dependencies sind schlecht!

Real World Dependency Injection

Page 10: Real World Dependency Injection - phpugffm13
Page 11: Real World Dependency Injection - phpugffm13
Page 12: Real World Dependency Injection - phpugffm13
Page 13: Real World Dependency Injection - phpugffm13
Page 14: Real World Dependency Injection - phpugffm13
Page 15: Real World Dependency Injection - phpugffm13

<?phpclass DeletePage extends Mvc_Action_AAction {

private $pageManager;

public function __construct() {$this->pageManager = new PageManager();

}

protected function execute(Mvc_Request $request) {$this->pageManager->delete(

(int) $request->get('pageId'));

}}

Real World Dependency Injection

„new“ is evil!

Page 16: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

„new“ is evil!

<?phpclass DeletePage extends Mvc_Action_AAction {

private $pageManager;

public function __construct(PageManager $pm) {$this->pageManager = $pm;

}

protected function execute(Mvc_Request $request) {$this->pageManager->delete(

(int) $request->get('pageId'));

}}

Page 17: Real World Dependency Injection - phpugffm13

"High-level modules should not depend on low-level modules.

Both should depend on abstractions."

Robert C. Martin

Real World Dependency Injection

Page 18: Real World Dependency Injection - phpugffm13
Page 19: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

„new“ is evil!

<?phpclass DeletePage extends Mvc_Action_AAction {

private $pageManager;

public function __construct(IPageManager $pm) {$this->pageManager = $pm;

}

protected function execute(Mvc_Request $request) {$this->pageManager->delete(

(int) $request->get('pageId'));

}}

Page 20: Real World Dependency Injection - phpugffm13

Wie verwaltet man Dependencies?

Real World Dependency Injection

Page 21: Real World Dependency Injection - phpugffm13
Page 22: Real World Dependency Injection - phpugffm13

Automatismus notwendig!

Simple Container vs. Full stacked DI Framework

Real World Dependency Injection

Page 23: Real World Dependency Injection - phpugffm13

Was ist Dependency Injection?

Real World Dependency Injection

Page 24: Real World Dependency Injection - phpugffm13

Was ist Dependency Injection?

Real World Dependency Injection

new DeletePage(new PageManager());

Page 25: Real World Dependency Injection - phpugffm13

Was ist Dependency Injection?

Consumer

Real World Dependency Injection

Page 26: Real World Dependency Injection - phpugffm13

Was ist Dependency Injection?

Consumer Dependencies

Real World Dependency Injection

Page 27: Real World Dependency Injection - phpugffm13

Was ist Dependency Injection?

Consumer Dependencies Container

Real World Dependency Injection

Page 28: Real World Dependency Injection - phpugffm13

Was ist Dependency Injection?

Consumer Dependencies Container

Real World Dependency Injection

Page 29: Real World Dependency Injection - phpugffm13
Page 30: Real World Dependency Injection - phpugffm13

Constructor Injection<?php

class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao;

public function __construct(ISampleDao $sampleDao) {$this->sampleDao = $sampleDao;

}}

Real World Dependency Injection

Page 31: Real World Dependency Injection - phpugffm13

Setter Injection<?php

class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao;

public function setSampleDao(ISampleDao $sampleDao){$this->sampleDao = $sampleDao;

}}

Real World Dependency Injection

Page 32: Real World Dependency Injection - phpugffm13

Interface Injection<?php

interface IApplicationContextAware { public function setCtx(IApplicationContext $ctx);}

Real World Dependency Injection

Page 33: Real World Dependency Injection - phpugffm13

Interface Injection<?php

class MySampleService implements IMySampleService,IApplicationContextAware { /** * @var IApplicationContext */ private $ctx;

public function setCtx(IApplicationContext $ctx) {$this->ctx = $ctx;

}}

Real World Dependency Injection

Page 34: Real World Dependency Injection - phpugffm13

Property Injection

Real World Dependency Injection

"NEIN NEIN NEIN!"David Zülke

Page 35: Real World Dependency Injection - phpugffm13
Page 36: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Annotations<?php

class MySampleService implements IMySampleService { private $sampleDao;

/** * @Inject */ public function __construct(ISampleDao $sampleDao) {

$this->sampleDao = $sampleDao; }}

Page 37: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Annotations<?php

class MySampleService implements IMySampleService { private $sampleDao;

/** * @Inject * @Named('TheSampleDao') */ public function __construct(ISampleDao $sampleDao) {

$this->sampleDao = $sampleDao; }}

Page 38: Real World Dependency Injection - phpugffm13

Externe Konfiguration - XML

<?xml version="1.0" encoding="UTF-8" ?><beans>

<bean id="SampleDao" class="SampleDao"><constructor-arg value="app_sample" /><constructor-arg value="iSampleId" /><constructor-arg value="BoSample" />

</bean>

<bean id="SampleService" class="MySampleService"><constructor-arg ref="SampleDao" />

</bean></beans>

Real World Dependency Injection

Page 39: Real World Dependency Injection - phpugffm13

Externe Konfiguration - YAML

services: SampleDao: class: SampleDao arguments: ['app_sample', 'iSampleId', 'BoSample'] SampleService: class: SampleService arguments: [@SampleDao]

Real World Dependency Injection

Page 40: Real World Dependency Injection - phpugffm13

Externe Konfiguration - PHP<?phpclass BeanCache extends Beanfactory_Container_PHP {

protected function createSampleDao() {$oBean = new SampleDao('app_sample',

'iSampleId', 'BoSample');return $oBean;

}

protected function createMySampleService() {$oBean = new MySampleService(

$this->getBean('SampleDao'));return $oBean;

}}

Real World Dependency Injection

Page 41: Real World Dependency Injection - phpugffm13

Interne vs. Externe Konfiguration

Real World Dependency Injection

Klassenkonfiguration vs.

Instanzkonfiguration

Page 42: Real World Dependency Injection - phpugffm13
Page 43: Real World Dependency Injection - phpugffm13

Unittesting einfach gemacht

Real World Dependency Injection

Page 44: Real World Dependency Injection - phpugffm13

Unittesting einfach gemacht<?phprequire_once 'PHPUnit/Framework.php';

class ServiceTest extends PHPUnit_Framework_TestCase { public function testSampleService() {

// set up dependencies $sampleDao = $this->getMock('ISampleDao'); $service = new MySampleService($sampleDao);

// run test case$return = $service->doWork();

// check assertions$this->assertTrue($return);

}}

Real World Dependency Injection

Page 45: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung

Real World Dependency Injection

Page 46: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung

Page ExporterPage Exporter

Released / PublishedPages

Released / PublishedPages

WorkingcopyPages

WorkingcopyPages

Real World Dependency Injection

Page 47: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung<?phpabstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; }}

Real World Dependency Injection

Page 48: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung<?phpabstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; }}

Zur Erinnerung: Der Vertrag!

Real World Dependency Injection

Page 49: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung<?phpclass PublishedPageExporter extends PageExporter { public function __construct() { $this->setPageDao(new PublishedPageDao()); }}

class WorkingCopyPageExporter extends PageExporter { public function __construct() { $this->setPageDao(new WorkingCopyPageDao()); }}

Real World Dependency Injection

Page 50: Real World Dependency Injection - phpugffm13

"Only deleted code is good code!"Oliver Gierke

Eine Klasse, mehrfache Ausprägung

Real World Dependency Injection

Page 51: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung<?phpclass PageExporter { public function __construct(IPageDao $pageDao) { $this->pageDao = $pageDao; }}

Real World Dependency Injection

Page 52: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung<?xml version="1.0" encoding="UTF-8" ?><beans>

<bean id="ExportLive" class="PageExporter"><constructor-arg ref="PublishedPageDao" />

</bean>

<bean id="ExportWorking" class="PageExporter"><constructor-arg ref="WorkingCopyPageDao" />

</bean></beans>

Real World Dependency Injection

Page 53: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung<?php

// create ApplicationContext instance$ctx = new ApplicationContext();

// retrieve live exporter$exporter = $ctx->getBean('ExportLive');

// retrieve working copy exporter$exporter = $ctx->getBean('ExportWorking');

Real World Dependency Injection

Page 54: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung II

Real World Dependency Injection

Page 55: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung II

http://editor.loc/page/[id]/headline/

http://editor.loc/page/[id]/content/

http://editor.loc/page/[id]/teaser/

Real World Dependency Injection

Page 56: Real World Dependency Injection - phpugffm13

<?phpclass EditPart extends Mvc_Action_AFormAction {

private $pagePartsManager;private $type;

public function __construct(IPagePartsManager $pm) {$this->pagePartsManager = $pm;

}

public function setType($ptype) {$this->type = (int) $type;

}

protected function process(Bo_ABo $formBackObj) {}

}

Eine Klasse, mehrfache Ausprägung II

Real World Dependency Injection

Page 57: Real World Dependency Injection - phpugffm13

Eine Klasse, mehrfache Ausprägung II<?xml version="1.0" encoding="UTF-8" ?><beans>

<bean id="EditHeadline" class="EditPart"><constructor-arg ref="PagePartDao" /><property name="Type" const="PType::Headline" />

</bean>

<bean id="EditContent" class="EditPart"><constructor-arg ref="PagePartDao" /><property name="Type" const="PType::Content" />

</bean>

</beans>

Real World Dependency Injection

Page 58: Real World Dependency Injection - phpugffm13

Externe Services mocken

Real World Dependency Injection

Page 59: Real World Dependency Injection - phpugffm13

Externe Services mocken

BookingmanagerBookingmanager WS-Konnektor

WS-Konnektor WebserviceWebservice

Real World Dependency Injection

Page 60: Real World Dependency Injection - phpugffm13

Externe Services mocken

BookingmanagerBookingmanager WS-Konnektor

WS-Konnektor WebserviceWebservice

Real World Dependency Injection

Zur Erinnerung: Der Vertrag!

Page 61: Real World Dependency Injection - phpugffm13

Externe Services mocken

BookingmanagerBookingmanager FS-Konnektor

FS-Konnektor FilesystemFilesystem

Real World Dependency Injection

Page 62: Real World Dependency Injection - phpugffm13

Externe Services mocken

BookingmanagerBookingmanager FS-Konnektor

FS-Konnektor FilesystemFilesystem

erfüllt denVertrag!

Real World Dependency Injection

Page 63: Real World Dependency Injection - phpugffm13

Sauberer, lesbarer Code

Real World Dependency Injection

Page 64: Real World Dependency Injection - phpugffm13

Sauberer, lesbarer Code<?phpclass DeletePage extends Mvc_Action_AAction {

private $pageManager;

public function __construct(IPageManager $pm) {$this->pageManager = $pm;

}

protected function execute(Mvc_Request $request) {$this->pageManager->delete(

(int) $request->get('pageId'));

return new ModelAndView($this->getSuccessView());}

}

Real World Dependency Injection

Page 65: Real World Dependency Injection - phpugffm13

Keine Framework Abhängigkeit

Real World Dependency Injection

Page 66: Real World Dependency Injection - phpugffm13

Keine Framework Abhängigkeit<?phpclass MySampleService implements IMySampleService { private $sampleDao;

public function __construct(ISampleDao $sampleDao) {$this->sampleDao = $sampleDao;

}

public function getSample($sampleId) {try { return $this->sampleDao->readById($sampleId);}catch(DaoException $exception) {}

}}

Real World Dependency Injection

Page 67: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Wie sieht das nun in der Praxis aus?

Page 68: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Pimple

Page 69: Real World Dependency Injection - phpugffm13

Pimple – Erste Schritte

Real World Dependency Injection

<?php

class TalkService {public function __construct() {}

public function getTalks() {}

}

Page 70: Real World Dependency Injection - phpugffm13

Pimple – Erste Schritte

Real World Dependency Injection

<?phprequire_once '/path/to/Pimple.php';require_once '/path/to/TalkService.php';

// create the Container$container = new Pimple();

// define talkService object in container$container['talkService'] = function ($c) { return new TalkService();};

// instantiate talkService from container$talkService = $container['talkService'];

Page 71: Real World Dependency Injection - phpugffm13

Pimple – Constructor Injection

Real World Dependency Injection

<?php

interface GenericRepository {public function readTalks();

}

class TalkRepository implements GenericRepository {public function readTalks() {}

}

class TalkService {public function __construct(TalkRepository $repo) {}

public function getTalks() {}

}

Page 72: Real World Dependency Injection - phpugffm13

Pimple – Constructor Injection

Real World Dependency Injection

<?phprequire_once '/path/to/Pimple.php';require_once '/path/to/TalkService.php';

// create the Container$container = new Pimple();

// define services in container$container['talkRepository'] = function ($c) { return new TalkRepository();};$container['talkService'] = function ($c) { return new TalkService($c['talkRepository']);};

// instantiate talkService from container$talkService = $container['talkService'];

Page 73: Real World Dependency Injection - phpugffm13

Pimple – Setter Injection

Real World Dependency Injection

<?php

class Logger {public function doLog($logMsg) {}

}

class TalkService {public function __construct(TalkRepository $repo) {}

public function setLogger(Logger $logger) {}

public function getTalks() {}

}

Page 74: Real World Dependency Injection - phpugffm13

Pimple – Setter Injection

Real World Dependency Injection

<?phprequire_once '/path/to/Pimple.php';require_once '/path/to/TalkService.php';

// create the Container$container = new Pimple();

// define services in container$container['logger'] = function ($c) { return new Logger();};$container['talkRepository'] = function ($c) { return new TalkRepository();};$container['talkService'] = function ($c) { $service = new TalkService($c['talkRepository']); $service->setLogger($c['logger']); return $service;};

// instantiate talkService from container$talkService = $container['talkService'];

Page 75: Real World Dependency Injection - phpugffm13

Pimple – Allgemeines

Real World Dependency Injection

<?phprequire_once '/path/to/Pimple.php';require_once '/path/to/TalkService.php';

// create the Container$container = new Pimple();

// define services in container$container['loggerShared'] = $c->share(function ($c) { return new Logger();)};$container['logger'] = function ($c) { return new Logger();};

// instantiate logger from container$logger = $container['logger'];

// instantiate shared logger from container (same instance!)$logger2 = $container['loggerShared'];$logger3 = $container['loggerShared'];

Page 76: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Bucket

Page 77: Real World Dependency Injection - phpugffm13

Bucket – Constructor Injection

Real World Dependency Injection

<?php

interface GenericRepository {public function readTalks();

}

class TalkRepository implements GenericRepository {public function readTalks() {}

}

class TalkService {public function __construct(TalkRepository $repo) {}

public function getTalks() {}

}

Page 78: Real World Dependency Injection - phpugffm13

Bucket – Constructor Injection

Real World Dependency Injection

<?phprequire_once '/path/to/bucket.inc.php';require_once '/path/to/TalkService.php';

// create the Container$container = new bucket_Container();

// instantiate talkService from container$talkService = $container->create('TalkService');

// instantiate shared instances from container$talkService2 = $container->get('TalkService');$talkService3 = $container->get('TalkService');

Page 79: Real World Dependency Injection - phpugffm13
Page 80: Real World Dependency Injection - phpugffm13

Zend\Di – Erste Schritte

Real World Dependency Injection

<?phpnamespace Acme;

class TalkService {public function __construct() {}

public function getTalks() {}

}

Page 81: Real World Dependency Injection - phpugffm13

Zend\Di – Erste Schritte

Real World Dependency Injection

<?php

$di = new \Zend\Di\Di();

$service = $di->get('Acme\TalkService');$service->getTalks();

Page 82: Real World Dependency Injection - phpugffm13

Zend\Di – Constructor Injection

Real World Dependency Injection

<?phpnamespace Acme;

interface GenericRepository {public function readTalks();

}

class TalkRepository implements GenericRepository {public function readTalks() {}

}

class TalkService {public function __construct(TalkRepository $repo) {}

public function getTalks() {}

}

Page 83: Real World Dependency Injection - phpugffm13

Zend\Di – Constructor Injection

Real World Dependency Injection

<?php

$di = new \Zend\Di\Di();

$service = $di->get('Acme\TalkService');$service->getTalks();

Page 84: Real World Dependency Injection - phpugffm13

Zend\Di – Setter Injection

Real World Dependency Injection

<?phpnamespace Acme;

class Logger {public function doLog($logMsg) {}

}

class TalkService {public function __construct(TalkRepository $repo) {}

public function setLogger(Logger $logger) {}

public function getTalks() {}

}

Page 85: Real World Dependency Injection - phpugffm13

Zend\Di – Setter Injection

Real World Dependency Injection

<?php$di = new \Zend\Di\Di();$di->configure(

new Zend\Di\Configuration(array(

'definition' => array('class' => array(

'Acme\TalkService' => array('setLogger' => array('required' => true)

))

))

));

$service = $di->get('Acme\TalkService');var_dump($service);

Page 86: Real World Dependency Injection - phpugffm13

Zend\Di – Interface Injection

Real World Dependency Injection

<?phpnamespace Acme;

class Logger {public function doLog($logMsg) {}

}

interface LoggerAware {public function setLogger(Logger $logger);

}

class TalkService implements LoggerAware {public function __construct(TalkRepository $repo) {}

public function setLogger(Logger $logger) {}

public function getTalks() {}

}

Page 87: Real World Dependency Injection - phpugffm13

Zend\Di – Interface Injection

Real World Dependency Injection

<?php

$di = new \Zend\Di\Di();

$service = $di->get('Acme\TalkService');$service->getTalks();

Page 88: Real World Dependency Injection - phpugffm13

Zend\Di – Grundsätzliches

Real World Dependency Injection

<?php

$di = new \Zend\Di\Di();

$service = $di->get('Acme\TalkService');var_dump($service);

$service2 = $di->get('Acme\TalkService');var_dump($service2); // same instance as $service

$service3 = $di->get('Acme\TalkService',array(

'repo' => new \phpbnl12\TalkRepository())

);var_dump($service3); // new instance

Page 89: Real World Dependency Injection - phpugffm13

Zend\Di – Builder Definition

Real World Dependency Injection

<?php// describe dependency$dep = new \Zend\Di\Definition\Builder\PhpClass();$dep->setName('Acme\TalkRepository');

// describe class$class = new \Zend\Di\Definition\Builder\PhpClass();$class->setName('Acme\TalkService');

// add injection method$im = new \Zend\Di\Definition\Builder\InjectionMethod();$im->setName('__construct');$im->addParameter('repo', 'Acme\TalkRepository');$class->addInjectionMethod($im);

// configure builder$builder = new \Zend\Di\Definition\BuilderDefinition();$builder->addClass($dep);$builder->addClass($class);

Page 90: Real World Dependency Injection - phpugffm13

Zend\Di – Builder Definition

Real World Dependency Injection

<?php

// add to Di$defList = new \Zend\Di\DefinitionList($builder);$di = new \Zend\Di\Di($defList);

$service = $di->get('Acme\TalkService');var_dump($service);

Page 91: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Zend\ServiceManager to the resuce!

Page 92: Real World Dependency Injection - phpugffm13
Page 93: Real World Dependency Injection - phpugffm13

Symfony2

Real World Dependency Injection

<?phpnamespace Acme\TalkBundle\Controller;use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class TalkController extends Controller { /** * @Route("/", name="_talk") * @Template() */ public function indexAction() { $service = $this->get('acme.talk.service'); return array(); }}

Page 94: Real World Dependency Injection - phpugffm13

Symfony2 – Konfigurationsdatei

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://symfony.com/schema/dic/services/services-1.0.xsd">

</container>

File services.xml in src/Acme/DemoBundle/Resources/config

Page 95: Real World Dependency Injection - phpugffm13

Symfony2 – Constructor Injection

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.repo"

class="Acme\TalkBundle\Service\TalkRepository" />

<service id="acme.talk.service" class="Acme\TalkBundle\Service\TalkService">

<argument type="service" id="acme.talk.repo" /></service>

</services></container>

Page 96: Real World Dependency Injection - phpugffm13

Symfony2 – Setter Injection

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.logger"

class="Acme\TalkBundle\Service\Logger" />

<service id="acme.talk.repo" class="Acme\TalkBundle\Service\TalkRepository" />

<service id="acme.talk.service" class="Acme\TalkBundle\Service\TalkService">

<argument type="service" id="acme.talk.repo" /><call method="setLogger">

<argument type="service" id="acme.talk.logger" /></call>

</service></services>

</container>

Page 97: Real World Dependency Injection - phpugffm13

Symfony2 – Setter Injection (optional)

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.logger"

class="Acme\TalkBundle\Service\Logger" />

<service id="acme.talk.repo" class="Acme\TalkBundle\Service\TalkRepository" />

<service id="acme.talk.service" class="Acme\TalkBundle\Service\TalkService">

<argument type="service" id="acme.talk.repo" /><call method="setLogger">

<argument type="service" id="acme.talk.logger" on-invalid="ignore" />

</call></service>

</services></container>

Page 98: Real World Dependency Injection - phpugffm13

Symfony2 – Property Injection

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.repo"

class="Acme\TalkBundle\Service\TalkRepository" />

<service id="acme.talk.service" class="Acme\TalkBundle\Service\TalkService">

<property name="talkRepository" type="service" id="acme.talk.repo" />

</service></services>

</container>

Page 99: Real World Dependency Injection - phpugffm13

Symfony2 – private / öffentliche Services

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.logger"

class="Acme\TalkBundle\Service\Logger" public="false" />

<service id="acme.talk.repo" class="Acme\TalkBundle\Service\TalkRepository" />

<service id="acme.talk.service" class="Acme\TalkBundle\Service\TalkService">

<argument type="service" id="acme.talk.repo" /><call method="setLogger">

<argument type="service" id="acme.talk.logger" /></call>

</service></services>

</container>

Page 100: Real World Dependency Injection - phpugffm13

Symfony2 – Vererbung

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.serviceparent"

class="Acme\TalkBundle\Service\TalkService" abstract="true"><property name="talkRepository" type="service"

id="acme.talk.repo" /></service>

<service id="acme.talk.service" parent="acme.talk.serviceparent" />

<service id="acme.talk.service2" parent="acme.talk.serviceparent" /></services>

</container>

Page 101: Real World Dependency Injection - phpugffm13

Symfony2 – Scoping

Real World Dependency Injection

<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services

http://symfony.com/schema/dic/services/services-1.0.xsd">

<services><service id="acme.talk.repo"

class="Acme\TalkBundle\Service\TalkRepository" />

<service id="acme.talk.service"class="Acme\TalkBundle\Service\TalkService" scope="prototype"><property name="talkRepository" type="service"

id="acme.talk.repo" /></service>

</services></container>

Page 102: Real World Dependency Injection - phpugffm13

Real World Dependency Injection

Page 103: Real World Dependency Injection - phpugffm13

Flow3 – Constructor Injection

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface */protected $talkService;

public function __construct(\Acme\Demo\Service\TalkService $talkService) {$this->talkService = $talkService;

}

public function indexAction() {}

}

Page 104: Real World Dependency Injection - phpugffm13

Flow3 – Constructor Injection (manuell)

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface */protected $talkService;

public function __construct(\Acme\Demo\Service\TalkService $talkService) {$this->talkService = $talkService;

}

public function indexAction() {}

}

Page 105: Real World Dependency Injection - phpugffm13

Flow3 – Setter Injection (manuell)

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface */protected $talkService;

public function setTalkService(\Acme\Demo\Service\TalkService $talkService) {$this->talkService = $talkService;

}

public function indexAction() {}

}

Page 106: Real World Dependency Injection - phpugffm13

Flow3 – Setter Injection (manuell)

Real World Dependency Injection

File Objects.yaml in Packages/Application/Acme.Demo/Configuration# @package AcmeAcme\Demo\Controller\StandardController: properties: talkService: object: Acme\Demo\Service\TalkService

Page 107: Real World Dependency Injection - phpugffm13

Flow3 – Setter Injection (automatisch)

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface */protected $talkService;

public function injectTalkService(\Acme\Demo\Service\TalkService $talkService) {$this->talkService = $talkService;

}

public function indexAction() {}

}

Page 108: Real World Dependency Injection - phpugffm13

Flow3 – Setter Injection (automatisch)

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface */protected $talkService;

public function injectSomethingElse(\Acme\Demo\Service\TalkService $talkService) {$this->talkService = $talkService;

}

public function indexAction() {}

}

Page 109: Real World Dependency Injection - phpugffm13

Flow3 – Property Injection

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkService * @FLOW3\Inject */protected $talkService;

public function indexAction() {}

}

Page 110: Real World Dependency Injection - phpugffm13

Flow3 – Property Injection (mittels Interface)

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface * @FLOW3\Inject */protected $talkService;

public function indexAction() {}

}

Page 111: Real World Dependency Injection - phpugffm13

Flow3 – Property Injection (mittels Interface)

Real World Dependency Injection

# @package AcmeAcme\Demo\Service\TalkServiceInterface: className: 'Acme\Demo\Service\TalkService'

File Objects.yaml in Packages/Application/Acme.Demo/Configuration

Page 112: Real World Dependency Injection - phpugffm13

Flow3 – Scoping

Real World Dependency Injection

<?phpnamespace Acme\Demo\Controller;

use TYPO3\FLOW3\Annotations as FLOW3;

/** * @FLOW3\Scope("session") */class StandardController extends \TYPO3\FLOW3\MVC\Controller\ActionController {

/** * @var \Acme\Demo\Service\TalkServiceInterface * @FLOW3\Inject */protected $talkService;

public function indexAction() {}

}

Page 113: Real World Dependency Injection - phpugffm13

Vorteile

Lose Kopplung, gesteigerte Wiederverwendbarkeit !

Real World Dependency Injection

Page 114: Real World Dependency Injection - phpugffm13

Vorteile

Codeumfang reduzieren,Fokus auf das Wesentliche!

Real World Dependency Injection

Page 115: Real World Dependency Injection - phpugffm13

Vorteile

Hilft Entwicklern den Code besser zu verstehen!

Real World Dependency Injection

Page 116: Real World Dependency Injection - phpugffm13

Nachteile – Kein JSR330 für PHP

Bucket, Crafty, FLOW3, Imind_Context, PicoContainer, Pimple,

Phemto, Stubbles, Symfony 2.0, Sphicy, Solar, Substrate, XJConf, Yadif,

Zend\Di , Lion Framework, Spiral Framework, Xyster Framework, …

Real World Dependency Injection

Page 117: Real World Dependency Injection - phpugffm13

Nachteile – Entwickler müssen umdenken

Konfiguration Laufzeit↔

Real World Dependency Injection

Page 118: Real World Dependency Injection - phpugffm13
Page 119: Real World Dependency Injection - phpugffm13

Vielen Dank!

Page 120: Real World Dependency Injection - phpugffm13

Image Creditshttp://www.sxc.hu/photo/1028452