Real World Dependency Injection - phpugffm13

Preview:

DESCRIPTION

 

Citation preview

Real World Dependency Injection

Über mich

Stephan Hochdörfer

Head of IT der bitExpert AG, Mannheim

PHP`ler seit 1999

S.Hochdoerfer@bitExpert.de

@shochdoerfer

Real World Dependency Injection

Was sind Dependencies?

Was sind Dependencies?

Applikation

Framework Bibliotheken

Real World Dependency Injection

Was sind Dependencies?

Controller

Service / Model

Datastore(s)

UtilsPHP Extensions

Real World Dependency Injection

Sind Dependencies schlecht?

Real World Dependency Injection

Sind Dependencies schlecht?

Dependencies sind nicht schlecht!

Real World Dependency Injection

Sind Dependencies schlecht?

Nützlich und sinnvoll!

Real World Dependency Injection

Sind Dependencies schlecht?

Fixe Dependencies sind schlecht!

Real World Dependency Injection

<?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!

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'));

}}

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

Both should depend on abstractions."

Robert C. Martin

Real World Dependency Injection

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'));

}}

Wie verwaltet man Dependencies?

Real World Dependency Injection

Automatismus notwendig!

Simple Container vs. Full stacked DI Framework

Real World Dependency Injection

Was ist Dependency Injection?

Real World Dependency Injection

Was ist Dependency Injection?

Real World Dependency Injection

new DeletePage(new PageManager());

Was ist Dependency Injection?

Consumer

Real World Dependency Injection

Was ist Dependency Injection?

Consumer Dependencies

Real World Dependency Injection

Was ist Dependency Injection?

Consumer Dependencies Container

Real World Dependency Injection

Was ist Dependency Injection?

Consumer Dependencies Container

Real World Dependency Injection

Constructor Injection<?php

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

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

}}

Real World Dependency Injection

Setter Injection<?php

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

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

}}

Real World Dependency Injection

Interface Injection<?php

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

Real World Dependency Injection

Interface Injection<?php

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

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

}}

Real World Dependency Injection

Property Injection

Real World Dependency Injection

"NEIN NEIN NEIN!"David Zülke

Real World Dependency Injection

Annotations<?php

class MySampleService implements IMySampleService { private $sampleDao;

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

$this->sampleDao = $sampleDao; }}

Real World Dependency Injection

Annotations<?php

class MySampleService implements IMySampleService { private $sampleDao;

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

$this->sampleDao = $sampleDao; }}

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

Externe Konfiguration - YAML

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

Real World Dependency Injection

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

Interne vs. Externe Konfiguration

Real World Dependency Injection

Klassenkonfiguration vs.

Instanzkonfiguration

Unittesting einfach gemacht

Real World Dependency Injection

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

Eine Klasse, mehrfache Ausprägung

Real World Dependency Injection

Eine Klasse, mehrfache Ausprägung

Page ExporterPage Exporter

Released / PublishedPages

Released / PublishedPages

WorkingcopyPages

WorkingcopyPages

Real World Dependency Injection

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

Real World Dependency Injection

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

Zur Erinnerung: Der Vertrag!

Real World Dependency Injection

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

"Only deleted code is good code!"Oliver Gierke

Eine Klasse, mehrfache Ausprägung

Real World Dependency Injection

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

Real World Dependency Injection

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

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

Eine Klasse, mehrfache Ausprägung II

Real World Dependency Injection

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

<?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

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

Externe Services mocken

Real World Dependency Injection

Externe Services mocken

BookingmanagerBookingmanager WS-Konnektor

WS-Konnektor WebserviceWebservice

Real World Dependency Injection

Externe Services mocken

BookingmanagerBookingmanager WS-Konnektor

WS-Konnektor WebserviceWebservice

Real World Dependency Injection

Zur Erinnerung: Der Vertrag!

Externe Services mocken

BookingmanagerBookingmanager FS-Konnektor

FS-Konnektor FilesystemFilesystem

Real World Dependency Injection

Externe Services mocken

BookingmanagerBookingmanager FS-Konnektor

FS-Konnektor FilesystemFilesystem

erfüllt denVertrag!

Real World Dependency Injection

Sauberer, lesbarer Code

Real World Dependency Injection

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

Keine Framework Abhängigkeit

Real World Dependency Injection

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

Real World Dependency Injection

Wie sieht das nun in der Praxis aus?

Real World Dependency Injection

Pimple

Pimple – Erste Schritte

Real World Dependency Injection

<?php

class TalkService {public function __construct() {}

public function getTalks() {}

}

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'];

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() {}

}

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'];

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() {}

}

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'];

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'];

Real World Dependency Injection

Bucket

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() {}

}

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');

Zend\Di – Erste Schritte

Real World Dependency Injection

<?phpnamespace Acme;

class TalkService {public function __construct() {}

public function getTalks() {}

}

Zend\Di – Erste Schritte

Real World Dependency Injection

<?php

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

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

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() {}

}

Zend\Di – Constructor Injection

Real World Dependency Injection

<?php

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

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

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() {}

}

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

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() {}

}

Zend\Di – Interface Injection

Real World Dependency Injection

<?php

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

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

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

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

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

Real World Dependency Injection

Zend\ServiceManager to the resuce!

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(); }}

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

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>

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>

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>

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>

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>

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>

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>

Real World Dependency Injection

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() {}

}

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() {}

}

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() {}

}

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

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() {}

}

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() {}

}

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() {}

}

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() {}

}

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

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() {}

}

Vorteile

Lose Kopplung, gesteigerte Wiederverwendbarkeit !

Real World Dependency Injection

Vorteile

Codeumfang reduzieren,Fokus auf das Wesentliche!

Real World Dependency Injection

Vorteile

Hilft Entwicklern den Code besser zu verstehen!

Real World Dependency Injection

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

Nachteile – Entwickler müssen umdenken

Konfiguration Laufzeit↔

Real World Dependency Injection

Vielen Dank!

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

Recommended