The state of DI in PHP - phpbnl12

Post on 13-Jan-2015

2.918 views 2 download

Tags:

description

 

Transcript of The state of DI in PHP - phpbnl12

The state of DI in PHP

The state of DI in PHP

About me

Stephan Hochdörfer, bitExpert AG

Department Manager Research Labs

enjoying PHP since 1999

7 years of DI experience (in PHP)

S.Hochdoerfer@bitExpert.de

@shochdoerfer

What`s this talk about?

The state of DI in PHP

What`s this talk about?

The state of DI in PHP

No framework bashing! Hopefully :)

What`s this talk about?

The state of DI in PHP

It`s all about how DI is implemented.

What`s DI about?

The state of DI in PHP

The state of DI in PHP

Inversion of control

The state of DI in PHP

„Hollywood principle“

What`s DI about?

The state of DI in PHP

new TalkService(new TalkRepository());

What`s DI about?

Consumer

The state of DI in PHP

What`s DI about?

Consumer Dependencies

The state of DI in PHP

What`s DI about?

Consumer Dependencies Container

The state of DI in PHP

What`s DI about?

Consumer Dependencies Container

The state of DI in PHP

A little bit of history...

The state of DI in PHP

1988

The state of DI in PHP

„Designing Reusable Classes“Ralph E. Johnson & Brian Foote

1996

The state of DI in PHP

„The Dependency Inversion Principle“Robert C. Martin

2002

The state of DI in PHP

2003

The state of DI in PHP

Spring Framework 0.9 released

2004

The state of DI in PHP

„Inversion of Control Containers and the Dependency Injection pattern“

Martin Fowler

2004

The state of DI in PHP

Spring Framework 1.0 released

2004

The state of DI in PHP

PHP 5.0 released

2005 / 2006

The state of DI in PHP

Garden, a lightweight DI container for PHP.

2006

The state of DI in PHP

First PHP5 framework with DI support

2007

The state of DI in PHP

International PHP Conference 2007 features 2 talks about DI.

2009

The state of DI in PHP

PHP 5.3.0 released

2010

The state of DI in PHP

Fabien Potencier talks about „Dependency Injection in

PHP 5.2 and 5.3“

2011

The state of DI in PHP

Symfony2, Flow3, Zend Framework 2 (beta)

2012

The state of DI in PHP

And now?

The state of DI in PHP

DI has finally arrived in the PHP world!

The state of DI in PHP

Let`s have a look at the different implementations!

The state of DI in PHP

Zend\Di – First steps

The state of DI in PHP

<?phpnamespace Acme;

class TalkService {public function __construct() {}

public function getTalks() {}

}

Zend\Di – First steps

The state of DI in PHP

<?php

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

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

Zend\Di – Constructor Injection

The state of DI in PHP

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

The state of DI in PHP

<?php

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

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

Zend\Di – Setter Injection

The state of DI in PHP

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

The state of DI in PHP

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

The state of DI in PHP

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

The state of DI in PHP

<?php

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

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

Zend\Di – General usage

The state of DI in PHP

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

The state of DI in PHP

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

The state of DI in PHP

<?php

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

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

The state of DI in PHP

Symfony2

The state of DI in PHP

<?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 – Configuration file

The state of DI in PHP

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

The state of DI in PHP

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

The state of DI in PHP

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

The state of DI in PHP

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

The state of DI in PHP

<?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/public Services

The state of DI in PHP

<?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 – Service inheritance

The state of DI in PHP

<?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 – Service scoping

The state of DI in PHP

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

The state of DI in PHP

Flow3 – Constructor Injection

The state of DI in PHP

<?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 (manually)

The state of DI in PHP

<?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 (manually)

The state of DI in PHP

<?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 (manually)

The state of DI in PHP

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

Flow3 – Setter Injection (Automagic)

The state of DI in PHP

<?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 (Automagic)

The state of DI in PHP

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

The state of DI in PHP

<?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 (with Interface)

The state of DI in PHP

<?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 (with Interface)

The state of DI in PHP

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

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

Flow3 – Scoping

The state of DI in PHP

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

}

The future?

The state of DI in PHP

The future (or what`s missing)?

The state of DI in PHP

The state of DI in PHP

PSR for DI container missing!

The state of DI in PHP

IDE support is missing...

Thank you!

http://joind.in/4768