SlideShare a Scribd company logo
Real World
Dependency Injection
     Special Edition :)
Real World Dependency Injection – Special Edition

 Über mich

  Stephan Hochdörfer, bitExpert AG
  Department Manager Research Labs
  PHP`ler seit 1999
  S.Hochdoerfer@bitExpert.de
  @shochdoerfer
Real World Dependency Injection – Special Edition

 Was sind Dependencies?
Real World Dependency Injection – Special Edition

 Sind Dependencies schlecht?
Real World Dependency Injection – Special Edition

 Sind Dependencies schlecht?




               Normalerweise nicht...
Real World Dependency Injection – Special Edition

 Sind Dependencies schlecht?




      …so lange Dependencies nicht
             hartcodiert sind!
Real World Dependency Injection – Special Edition


 Starke Kopplung
Real World Dependency Injection – Special Edition




 Keine Wiederverwendung!
Real World Dependency Injection – Special Edition




 Keine Isolation, nicht testbar!
Real World Dependency Injection – Special Edition




 Dependency Wahnsinn!
Real World Dependency Injection – Special Edition




                                s




 „new“ is evil!
Real World Dependency Injection – Special Edition

 „new“ is evil!
 <?php
 class 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 – Special Edition

 „new“ is evil!
 <?php
 class 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')
        );
     }
 }
Real World Dependency Injection – Special Edition




        "High-level modules should not
         depend on low-level modules.
            Both should depend on
                 abstractions."
                         Robert C. Martin
Real World Dependency Injection – Special Edition



 Interfaces als Vertrag
Real World Dependency Injection – Special Edition

 „new“ is evil!
 <?php
 class 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')
        );
     }
 }
Real World Dependency Injection – Special Edition

 Wie verwaltet man Dependencies?
Real World Dependency Injection – Special Edition



 Händisch? Mit der heißen Nadel gestrickt...
Real World Dependency Injection – Special Edition

 Automatismus notwendig!




     Einfacher Container        vs.         Fullstack
                                         DI Framework
Real World Dependency Injection – Special Edition

 Was ist Dependency Injection?




    Consumer
Real World Dependency Injection – Special Edition

 Was ist Dependency Injection?




    Consumer              Dependencies
Real World Dependency Injection – Special Edition

 Was ist Dependency Injection?




    Consumer              Dependencies              Container
Real World Dependency Injection – Special Edition

 Was ist Dependency Injection?




    Consumer              Dependencies              Container
Real World Dependency Injection – Special Edition




 Wie Dependencies injizieren?
Real World Dependency Injection – Special Edition

 Constructor Injection
 <?php

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

     public function __construct(ISampleDao $sampleDao) {
       $this->sampleDao = $sampleDao;
     }
 }
Real World Dependency Injection – Special Edition

 Setter Injection
 <?php

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

     public function setSampleDao(ISampleDao $sampleDao){
      $this->sampleDao = $sampleDao;
     }
 }
Real World Dependency Injection – Special Edition

 Interface Injection
 <?php

 interface IApplicationContextAware {
   public function setCtx(IApplicationContext $ctx);
 }
Real World Dependency Injection – Special Edition

 Interface Injection
 <?php

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

     public function setCtx(IApplicationContext $ctx) {
      $this->ctx = $ctx;
     }
 }
Real World Dependency Injection – Special Edition




 Wie verbinden wir nun alles?
Real World Dependency Injection – Special Edition

 Annotations
 <?php

 class MySampleService implements IMySampleService {
   private $sampleDao;

     /**
      * @Inject
      */
     public function __construct(ISampleDao $sampleDao)
     {
         $this->sampleDao = $sampleDao;
     }
 }
Real World Dependency Injection – Special Edition

 Annotations
 <?php

 class MySampleService implements IMySampleService {
   private $sampleDao;

     /**
      * @Inject
      * @Named('TheSampleDao')
      */
     public function __construct(ISampleDao $sampleDao)
     {
         $this->sampleDao = $sampleDao;
     }
 }
Real World Dependency Injection – Special Edition

 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 – Special Edition

 Externe Konfiguration - YAML

 services:
   SampleDao:
     class: SampleDao
     arguments: ['app_sample', 'iSampleId', 'BoSample']
   SampleService:
     class: SampleService
     arguments: [@SampleDao]
Real World Dependency Injection – Special Edition

 Externe Konfiguration - PHP
 <?php
 class 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 – Special Edition



 Beispiele gefällig?
Real World Dependency Injection – Special Edition

 Unittesting einfach gemacht
Real World Dependency Injection – Special Edition

 Unittesting einfach gemacht
 <?php
 require_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 – Special Edition

 Eine Klasse, mehrfache Ausprägung
Real World Dependency Injection – Special Edition

 Eine Klasse, mehrfache Ausprägung


                          Page Exporter
                           Page Exporter
Real World Dependency Injection – Special Edition

 Eine Klasse, mehrfache Ausprägung


                               Page Exporter
                                Page Exporter




       Released / /Published
        Released Published                      Workingcopy
                                                Workingcopy
              Pages
               Pages                              Pages
                                                   Pages
Real World Dependency Injection – Special Edition

 Eine Klasse, mehrfache Ausprägung
 <?php
 abstract class PageExporter {
   protected function setPageDao(IPageDao $pageDao) {
     $this->pageDao = $pageDao;
   }
 }
Real World Dependency Injection – Special Edition

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


                                   Zur Erinnerung:
                                    Der Vertrag!
Real World Dependency Injection – Special Edition

 Eine Klasse, mehrfache Ausprägung
 <?php
 class 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 – Special Edition

 Eine Klasse, mehrfache Ausprägung




     "Only deleted code is good code!"
                         Oliver Gierke
Real World Dependency Injection – Special Edition

 Eine Klasse, mehrfache Ausprägung
 <?php
 class PageExporter {
   public function __construct(IPageDao $pageDao) {
     $this->pageDao = $pageDao;
   }
 }
Real World Dependency Injection – Special Edition

 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 – Special Edition

 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 – Special Edition

 Eine Klasse, mehrfache Ausprägung II
Real World Dependency Injection – Special Edition

 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 – Special Edition

 Eine Klasse, mehrfache Ausprägung II
 <?php
 class 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) {
     }
 }
Real World Dependency Injection – Special Edition

 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 – Special Edition

 Externe Services mocken
Real World Dependency Injection – Special Edition

 Externe Services mocken




                                WS-
                                 WS-
  Bookingmanager
   Bookingmanager                                   Webservice
                                                    Webservice
                              Connector
                               Connector
Real World Dependency Injection – Special Edition

 Externe Services mocken




                                WS-
                                 WS-
  Bookingmanager
   Bookingmanager                                   Webservice
                                                    Webservice
                              Connector
                               Connector




               Zur Erinnerung:
                Der Vertrag!
Real World Dependency Injection – Special Edition

 Externe Services mocken




                                 FS-
                                  FS-
  Bookingmanager
   Bookingmanager                                   Filesystem
                                                     Filesystem
                              Connector
                               Connector
Real World Dependency Injection – Special Edition

 Externe Services mocken




                                     FS-
                                      FS-
  Bookingmanager
   Bookingmanager                                   Filesystem
                                                     Filesystem
                                  Connector
                                   Connector




                    erfüllt den
                     Vertrag!
Real World Dependency Injection – Special Edition

 Sauberer, lesbarer Code
Real World Dependency Injection – Special Edition

 Sauberer, lesbarer Code
 <?php
 class 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 – Special Edition

 Keine Framework Abhängigkeit
Real World Dependency Injection – Special Edition

 Keine Framework Abhängigkeit
 <?php
 class 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 – Special Edition




    Wie sieht das nun in der Praxis aus?
Real World Dependency Injection – Special Edition
Real World Dependency Injection – Special Edition

 ZendDi – Erste Schritte
 <?php
 namespace Acme;

 class TalkService {
     public function __construct() {
     }

     public function getTalks() {
     }
 }
Real World Dependency Injection – Special Edition

 ZendDi – Erste Schritte
 <?php

 $di = new ZendDiDi();

 $service = $di->get('AcmeTalkService');
 $service->getTalks();
Real World Dependency Injection – Special Edition

 ZendDi – Constructor Injection
 <?php
 namespace Acme;

 interface GenericRepository {
     public function readTalks();
 }


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


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

     public function getTalks() {
     }
 }
Real World Dependency Injection – Special Edition

 ZendDi – Constructor Injection
 <?php

 $di = new ZendDiDi();

 $service = $di->get('AcmeTalkService');
 $service->getTalks();
Real World Dependency Injection – Special Edition

 ZendDi – Setter Injection
 <?php
 namespace Acme;

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

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

     public function setLogger(Logger $logger) {
     }

     public function getTalks() {
     }
 }
Real World Dependency Injection – Special Edition

 ZendDi – Setter Injection
 <?php
 $di = new ZendDiDi();
 $di->configure(
     new ZendDiConfiguration(
          array(
              'definition' => array(
                  'class' => array(
                           'AcmeTalkService' => array(
                                    'setLogger' => array('required' => true)
                           )
                  )
              )
          )
     )
 );

 $service = $di->get('AcmeTalkService');
 var_dump($service);
Real World Dependency Injection – Special Edition

 ZendDi – Interface Injection
 <?php
 namespace 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() {
     }
 }
Real World Dependency Injection – Special Edition

 ZendDi – Interface Injection
 <?php

 $di = new ZendDiDi();

 $service = $di->get('AcmeTalkService');
 $service->getTalks();
Real World Dependency Injection – Special Edition

 ZendDi – Grundsätzliches
 <?php

 $di = new ZendDiDi();

 $service = $di->get('AcmeTalkService');
 var_dump($service);


 $service2 = $di->get('AcmeTalkService');
 var_dump($service2); // gleiche Instanz wie $service


 $service3 = $di->get(
     'AcmeTalkService',
     array(
          'repo' => new phpbnl12TalkRepository()
     )
 );
 var_dump($service3); // neue Instanz
Real World Dependency Injection – Special Edition

 ZendDi – Builder Definition
 <?php
 // Dependency beschreiben
 $dep = new ZendDiDefinitionBuilderPhpClass();
 $dep->setName('AcmeTalkRepository');

 // Klasse beschreiben
 $class = new ZendDiDefinitionBuilderPhpClass();
 $class->setName('AcmeTalkService');

 // Injection Methode beschreiben
 $im = new ZendDiDefinitionBuilderInjectionMethod();
 $im->setName('__construct');
 $im->addParameter('repo', 'AcmeTalkRepository');
 $class->addInjectionMethod($im);

 // Builder konfigurieren
 $builder = new ZendDiDefinitionBuilderDefinition();
 $builder->addClass($dep);
 $builder->addClass($class);
Real World Dependency Injection – Special Edition

 ZendDi – Builder Definition
 <?php

 // zur DefinitionList hinzufügen
 $defList = new ZendDiDefinitionList($builder);
 $di = new ZendDiDi($defList);

 $service = $di->get('AcmeTalkService');
 var_dump($service);
Real World Dependency Injection – Special Edition
Real World Dependency Injection – Special Edition

 Symfony2
 <?php
 namespace AcmeTalkBundleController;
 use SymfonyBundleFrameworkBundleControllerController;
 use SensioBundleFrameworkExtraBundleConfigurationRoute;
 use SensioBundleFrameworkExtraBundleConfigurationTemplate;

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

 Symfony2 – Konfigurationsdatei
 Datei services.xml in src/Acme/DemoBundle/Resources/config
 <?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">


 </container>
Real World Dependency Injection – Special Edition

 Symfony2 – Constructor 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="AcmeTalkBundleServiceTalkRepository" />

          <service id="acme.talk.service"
              class="AcmeTalkBundleServiceTalkService">
              <argument type="service" id="acme.talk.repo" />
          </service>
     </services>
 </container>
Real World Dependency Injection – Special Edition

 Symfony2 – Setter 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="AcmeTalkBundleServiceLogger" />

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

          <service id="acme.talk.service"
              class="AcmeTalkBundleServiceTalkService">
              <argument type="service" id="acme.talk.repo" />
              <call method="setLogger">
                   <argument type="service" id="acme.talk.logger" />
              </call>
          </service>
     </services>
 </container>
Real World Dependency Injection – Special Edition

 Symfony2 – Setter Injection (optional)
 <?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="AcmeTalkBundleServiceLogger" />

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

          <service id="acme.talk.service"
              class="AcmeTalkBundleServiceTalkService">
              <argument type="service" id="acme.talk.repo" />
              <call method="setLogger">
                   <argument type="service" id="acme.talk.logger"
                        on-invalid="ignore" />
              </call>
          </service>
     </services>
 </container>
Real World Dependency Injection – Special Edition

 Symfony2 – Property 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="AcmeTalkBundleServiceTalkRepository" />

          <service id="acme.talk.service"
              class="AcmeTalkBundleServiceTalkService">
              <property name="talkRepository" type="service"
                  id="acme.talk.repo" />
          </service>
     </services>
 </container>
Real World Dependency Injection – Special Edition

 Symfony2 – private / öffentliche Services
 <?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="AcmeTalkBundleServiceLogger" public="false" />

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

          <service id="acme.talk.service"
              class="AcmeTalkBundleServiceTalkService">
              <argument type="service" id="acme.talk.repo" />
              <call method="setLogger">
                   <argument type="service" id="acme.talk.logger" />
              </call>
          </service>
     </services>
 </container>
Real World Dependency Injection – Special Edition

 Symfony2 – Vererbung
 <?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="AcmeTalkBundleServiceTalkService" 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>
Real World Dependency Injection – Special Edition

 Symfony2 – Scoping
 <?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="AcmeTalkBundleServiceTalkRepository" />

          <service id="acme.talk.service"
              class="AcmeTalkBundleServiceTalkService" scope="prototype">
              <property name="talkRepository" type="service"
                   id="acme.talk.repo" />
          </service>
     </services>
 </container>
Real World Dependency Injection – Special Edition
Real World Dependency Injection – Special Edition

 Flow3 – Constructor Injection
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkServiceInterface
      */
     protected $talkService;

     public function __construct(
         AcmeDemoServiceTalkService $talkService) {
         $this->talkService = $talkService;
     }

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Flow3 – Setter Injection (manuell)
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkServiceInterface
      */
     protected $talkService;

     public function setTalkService(
         AcmeDemoServiceTalkService $talkService) {
         $this->talkService = $talkService;
     }

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Flow3 – Setter Injection (manuell)
 Datei Objects.yaml in Packages/Application/Acme.Demo/Configuration
 # @package Acme
 AcmeDemoControllerStandardController:
   properties:
     talkService:
       object: AcmeDemoServiceTalkService
Real World Dependency Injection – Special Edition

 Flow3 – Setter Injection (automatisch)
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkServiceInterface
      */
     protected $talkService;

     public function injectTalkService(
         AcmeDemoServiceTalkService $talkService) {
         $this->talkService = $talkService;
     }

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Flow3 – Setter Injection (automatisch)
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkServiceInterface
      */
     protected $talkService;

     public function injectSomethingElse(
         AcmeDemoServiceTalkService $talkService) {
         $this->talkService = $talkService;
     }

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Flow3 – Property Injection
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkService
      * @FLOW3Inject
      */
     protected $talkService;

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Flow3 – Property Injection (mittels Interface)
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkServiceInterface
      * @FLOW3Inject
      */
     protected $talkService;

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Flow3 – Property Injection (mittels Interface)
 Datei Objects.yaml in Packages/Application/Acme.Demo/Configuration
 # @package Acme
 AcmeDemoServiceTalkServiceInterface:
   className: 'AcmeDemoServiceTalkService'
Real World Dependency Injection – Special Edition

 Flow3 – Scoping
 <?php
 namespace AcmeDemoController;

 use TYPO3FLOW3Annotations as FLOW3;

 /**
  * @FLOW3Scope("session")
  */
 class StandardController extends TYPO3FLOW3MVCControllerActionController {
     /**
      * @var AcmeDemoServiceTalkServiceInterface
      * @FLOW3Inject
      */
     protected $talkService;

     public function indexAction() {
     }
 }
Real World Dependency Injection – Special Edition

 Vorteile
Real World Dependency Injection – Special Edition

 Vorteile




              Lose Kopplung,
    gesteigerte Wiederverwendbarkeit !
Real World Dependency Injection – Special Edition

 Vorteile




            Codeumfang reduzieren,
           Fokus auf das Wesentliche!
Real World Dependency Injection – Special Edition

 Vorteile




           Hilft Entwicklern den Code
               besser zu verstehen!
Real World Dependency Injection – Special Edition

 Nachteil – Kein JSR330 für PHP


  Bucket, Crafty, FLOW3, Imind_Context,
      PicoContainer, Pimple, Phemto,
   Stubbles, Symfony 2.0, Sphicy, Solar,
  Substrate, XJConf, Yadif, ZendDi , Lion
  Framework, Spiral Framework, Xyster
              Framework, …
Real World Dependency Injection – Special Edition

 Nachteil – Entwickler müssen umdenken




             Konfiguration ↔ Laufzeit
Real World Dependency Injection – Special Edition




 Nachteil – Keine IDE Unterstützung!
Vielen Dank!
Image Credits
http://www.sxc.hu/photo/1028452

More Related Content

PDF
Real World Dependency Injection - PFCongres 2010
PDF
Testing untestable code - oscon 2012
PDF
Dependency Injection in PHP - dwx13
PDF
Real World Dependency Injection - phpugffm13
PDF
Real world dependency injection - DPC10
PDF
Testing untestable code - phpday
PDF
Real World Dependency Injection - phpday
PDF
Real World Dependency Injection - IPC11 Spring Edition
Real World Dependency Injection - PFCongres 2010
Testing untestable code - oscon 2012
Dependency Injection in PHP - dwx13
Real World Dependency Injection - phpugffm13
Real world dependency injection - DPC10
Testing untestable code - phpday
Real World Dependency Injection - phpday
Real World Dependency Injection - IPC11 Spring Edition

What's hot (19)

PDF
Testing untestable code - DPC10
PDF
Testing untestable Code - PFCongres 2010
KEY
IoC with PHP
PPS
Authentication with zend framework
PDF
ioc-castle-windsor
PDF
Create Your Own Framework by Fabien Potencier
ODP
Dependency Injection, Zend Framework and Symfony Container
PDF
Instant ACLs with Zend Framework 2
PDF
Enterprise Security API (ESAPI) Java - Java User Group San Antonio
ODP
Implementing security routines with zf2
PDF
Seven Versions of One Web Application
PPT
Contexts and Dependency Injection for the JavaEE platform
PDF
Real World Dependency Injection - oscon13
PPT
Enterprise java beans(ejb) update 2
PDF
Vaadin with Java EE 7
PDF
JDT Fundamentals 2010
PPT
Spring talk111204
ODP
YAML is the new Eval
PPT
Enterprise Java Beans( E)
Testing untestable code - DPC10
Testing untestable Code - PFCongres 2010
IoC with PHP
Authentication with zend framework
ioc-castle-windsor
Create Your Own Framework by Fabien Potencier
Dependency Injection, Zend Framework and Symfony Container
Instant ACLs with Zend Framework 2
Enterprise Security API (ESAPI) Java - Java User Group San Antonio
Implementing security routines with zf2
Seven Versions of One Web Application
Contexts and Dependency Injection for the JavaEE platform
Real World Dependency Injection - oscon13
Enterprise java beans(ejb) update 2
Vaadin with Java EE 7
JDT Fundamentals 2010
Spring talk111204
YAML is the new Eval
Enterprise Java Beans( E)

More from Stephan Hochdörfer (20)

PDF
Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
PDF
Phing for power users - frOSCon8
PDF
Offline strategies for HTML5 web applications - frOSCon8
PDF
Offline Strategies for HTML5 Web Applications - oscon13
PDF
Offline Strategien für HTML5 Web Applikationen - dwx13
PDF
Your Business. Your Language. Your Code - dpc13
PDF
Phing for power users - dpc_uncon13
PDF
Offline Strategies for HTML5 Web Applications - ipc13
PDF
Offline-Strategien für HTML5 Web Applikationen - wmka
PDF
Offline-Strategien für HTML5 Web Applikationen - bedcon13
PDF
Testing untestable code - ConFoo13
PDF
A Phing fairy tale - ConFoo13
PDF
Offline strategies for HTML5 web applications - ConFoo13
PDF
Offline-Strategien für HTML5Web Applikationen - WMMRN12
PDF
Testing untestable code - IPC12
PDF
Offline strategies for HTML5 web applications - IPC12
PDF
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
PDF
Offline strategies for HTML5 web applications - pfCongres2012
PDF
Wie Software-Generatoren die Welt verändern können - Herbstcampus12
PDF
Testing untestable code - Herbstcampus12
Offline. Na und? Strategien für offlinefähige Applikationen in HTML5 - Herbst...
Phing for power users - frOSCon8
Offline strategies for HTML5 web applications - frOSCon8
Offline Strategies for HTML5 Web Applications - oscon13
Offline Strategien für HTML5 Web Applikationen - dwx13
Your Business. Your Language. Your Code - dpc13
Phing for power users - dpc_uncon13
Offline Strategies for HTML5 Web Applications - ipc13
Offline-Strategien für HTML5 Web Applikationen - wmka
Offline-Strategien für HTML5 Web Applikationen - bedcon13
Testing untestable code - ConFoo13
A Phing fairy tale - ConFoo13
Offline strategies for HTML5 web applications - ConFoo13
Offline-Strategien für HTML5Web Applikationen - WMMRN12
Testing untestable code - IPC12
Offline strategies for HTML5 web applications - IPC12
Große Systeme, lose Kopplung, Spaß bei der Arbeit! - WDC12
Offline strategies for HTML5 web applications - pfCongres2012
Wie Software-Generatoren die Welt verändern können - Herbstcampus12
Testing untestable code - Herbstcampus12

Recently uploaded (20)

PDF
Machine learning based COVID-19 study performance prediction
PPT
Teaching material agriculture food technology
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
KodekX | Application Modernization Development
PDF
Encapsulation theory and applications.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Big Data Technologies - Introduction.pptx
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
cuic standard and advanced reporting.pdf
Machine learning based COVID-19 study performance prediction
Teaching material agriculture food technology
Digital-Transformation-Roadmap-for-Companies.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
20250228 LYD VKU AI Blended-Learning.pptx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
KodekX | Application Modernization Development
Encapsulation theory and applications.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Network Security Unit 5.pdf for BCA BBA.
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Big Data Technologies - Introduction.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
The Rise and Fall of 3GPP – Time for a Sabbatical?
Understanding_Digital_Forensics_Presentation.pptx
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Review of recent advances in non-invasive hemoglobin estimation
cuic standard and advanced reporting.pdf

Real World Dependency Injection SE - phpugrhh

  • 1. Real World Dependency Injection Special Edition :)
  • 2. Real World Dependency Injection – Special Edition Über mich  Stephan Hochdörfer, bitExpert AG  Department Manager Research Labs  PHP`ler seit 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • 3. Real World Dependency Injection – Special Edition Was sind Dependencies?
  • 4. Real World Dependency Injection – Special Edition Sind Dependencies schlecht?
  • 5. Real World Dependency Injection – Special Edition Sind Dependencies schlecht? Normalerweise nicht...
  • 6. Real World Dependency Injection – Special Edition Sind Dependencies schlecht? …so lange Dependencies nicht hartcodiert sind!
  • 7. Real World Dependency Injection – Special Edition Starke Kopplung
  • 8. Real World Dependency Injection – Special Edition Keine Wiederverwendung!
  • 9. Real World Dependency Injection – Special Edition Keine Isolation, nicht testbar!
  • 10. Real World Dependency Injection – Special Edition Dependency Wahnsinn!
  • 11. Real World Dependency Injection – Special Edition s „new“ is evil!
  • 12. Real World Dependency Injection – Special Edition „new“ is evil! <?php class 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') ); } }
  • 13. Real World Dependency Injection – Special Edition „new“ is evil! <?php class 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') ); } }
  • 14. Real World Dependency Injection – Special Edition "High-level modules should not depend on low-level modules. Both should depend on abstractions." Robert C. Martin
  • 15. Real World Dependency Injection – Special Edition Interfaces als Vertrag
  • 16. Real World Dependency Injection – Special Edition „new“ is evil! <?php class 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') ); } }
  • 17. Real World Dependency Injection – Special Edition Wie verwaltet man Dependencies?
  • 18. Real World Dependency Injection – Special Edition Händisch? Mit der heißen Nadel gestrickt...
  • 19. Real World Dependency Injection – Special Edition Automatismus notwendig! Einfacher Container vs. Fullstack DI Framework
  • 20. Real World Dependency Injection – Special Edition Was ist Dependency Injection? Consumer
  • 21. Real World Dependency Injection – Special Edition Was ist Dependency Injection? Consumer Dependencies
  • 22. Real World Dependency Injection – Special Edition Was ist Dependency Injection? Consumer Dependencies Container
  • 23. Real World Dependency Injection – Special Edition Was ist Dependency Injection? Consumer Dependencies Container
  • 24. Real World Dependency Injection – Special Edition Wie Dependencies injizieren?
  • 25. Real World Dependency Injection – Special Edition Constructor Injection <?php class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao; public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } }
  • 26. Real World Dependency Injection – Special Edition Setter Injection <?php class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao; public function setSampleDao(ISampleDao $sampleDao){ $this->sampleDao = $sampleDao; } }
  • 27. Real World Dependency Injection – Special Edition Interface Injection <?php interface IApplicationContextAware { public function setCtx(IApplicationContext $ctx); }
  • 28. Real World Dependency Injection – Special Edition Interface Injection <?php class MySampleService implements IMySampleService, IApplicationContextAware { /** * @var IApplicationContext */ private $ctx; public function setCtx(IApplicationContext $ctx) { $this->ctx = $ctx; } }
  • 29. Real World Dependency Injection – Special Edition Wie verbinden wir nun alles?
  • 30. Real World Dependency Injection – Special Edition Annotations <?php class MySampleService implements IMySampleService { private $sampleDao; /** * @Inject */ public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } }
  • 31. Real World Dependency Injection – Special Edition Annotations <?php class MySampleService implements IMySampleService { private $sampleDao; /** * @Inject * @Named('TheSampleDao') */ public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } }
  • 32. Real World Dependency Injection – Special Edition 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>
  • 33. Real World Dependency Injection – Special Edition Externe Konfiguration - YAML services: SampleDao: class: SampleDao arguments: ['app_sample', 'iSampleId', 'BoSample'] SampleService: class: SampleService arguments: [@SampleDao]
  • 34. Real World Dependency Injection – Special Edition Externe Konfiguration - PHP <?php class 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; } }
  • 35. Real World Dependency Injection – Special Edition Beispiele gefällig?
  • 36. Real World Dependency Injection – Special Edition Unittesting einfach gemacht
  • 37. Real World Dependency Injection – Special Edition Unittesting einfach gemacht <?php require_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); } }
  • 38. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung
  • 39. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung Page Exporter Page Exporter
  • 40. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung Page Exporter Page Exporter Released / /Published Released Published Workingcopy Workingcopy Pages Pages Pages Pages
  • 41. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung <?php abstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; } }
  • 42. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung <?php abstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Zur Erinnerung: Der Vertrag!
  • 43. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung <?php class PublishedPageExporter extends PageExporter { public function __construct() { $this->setPageDao(new PublishedPageDao()); } } class WorkingCopyPageExporter extends PageExporter { public function __construct() { $this->setPageDao(new WorkingCopyPageDao()); } }
  • 44. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung "Only deleted code is good code!" Oliver Gierke
  • 45. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung <?php class PageExporter { public function __construct(IPageDao $pageDao) { $this->pageDao = $pageDao; } }
  • 46. Real World Dependency Injection – Special Edition 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>
  • 47. Real World Dependency Injection – Special Edition 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');
  • 48. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung II
  • 49. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung II http://editor.loc/page/[id]/headline/ http://editor.loc/page/[id]/content/ http://editor.loc/page/[id]/teaser/
  • 50. Real World Dependency Injection – Special Edition Eine Klasse, mehrfache Ausprägung II <?php class 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) { } }
  • 51. Real World Dependency Injection – Special Edition 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>
  • 52. Real World Dependency Injection – Special Edition Externe Services mocken
  • 53. Real World Dependency Injection – Special Edition Externe Services mocken WS- WS- Bookingmanager Bookingmanager Webservice Webservice Connector Connector
  • 54. Real World Dependency Injection – Special Edition Externe Services mocken WS- WS- Bookingmanager Bookingmanager Webservice Webservice Connector Connector Zur Erinnerung: Der Vertrag!
  • 55. Real World Dependency Injection – Special Edition Externe Services mocken FS- FS- Bookingmanager Bookingmanager Filesystem Filesystem Connector Connector
  • 56. Real World Dependency Injection – Special Edition Externe Services mocken FS- FS- Bookingmanager Bookingmanager Filesystem Filesystem Connector Connector erfüllt den Vertrag!
  • 57. Real World Dependency Injection – Special Edition Sauberer, lesbarer Code
  • 58. Real World Dependency Injection – Special Edition Sauberer, lesbarer Code <?php class 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()); } }
  • 59. Real World Dependency Injection – Special Edition Keine Framework Abhängigkeit
  • 60. Real World Dependency Injection – Special Edition Keine Framework Abhängigkeit <?php class 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) {} } }
  • 61. Real World Dependency Injection – Special Edition Wie sieht das nun in der Praxis aus?
  • 62. Real World Dependency Injection – Special Edition
  • 63. Real World Dependency Injection – Special Edition ZendDi – Erste Schritte <?php namespace Acme; class TalkService { public function __construct() { } public function getTalks() { } }
  • 64. Real World Dependency Injection – Special Edition ZendDi – Erste Schritte <?php $di = new ZendDiDi(); $service = $di->get('AcmeTalkService'); $service->getTalks();
  • 65. Real World Dependency Injection – Special Edition ZendDi – Constructor Injection <?php namespace Acme; interface GenericRepository { public function readTalks(); } class TalkRepository implements GenericRepository { public function readTalks() { } } class TalkService { public function __construct(TalkRepository $repo) { } public function getTalks() { } }
  • 66. Real World Dependency Injection – Special Edition ZendDi – Constructor Injection <?php $di = new ZendDiDi(); $service = $di->get('AcmeTalkService'); $service->getTalks();
  • 67. Real World Dependency Injection – Special Edition ZendDi – Setter Injection <?php namespace Acme; class Logger { public function doLog($logMsg) { } } class TalkService { public function __construct(TalkRepository $repo) { } public function setLogger(Logger $logger) { } public function getTalks() { } }
  • 68. Real World Dependency Injection – Special Edition ZendDi – Setter Injection <?php $di = new ZendDiDi(); $di->configure( new ZendDiConfiguration( array( 'definition' => array( 'class' => array( 'AcmeTalkService' => array( 'setLogger' => array('required' => true) ) ) ) ) ) ); $service = $di->get('AcmeTalkService'); var_dump($service);
  • 69. Real World Dependency Injection – Special Edition ZendDi – Interface Injection <?php namespace 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() { } }
  • 70. Real World Dependency Injection – Special Edition ZendDi – Interface Injection <?php $di = new ZendDiDi(); $service = $di->get('AcmeTalkService'); $service->getTalks();
  • 71. Real World Dependency Injection – Special Edition ZendDi – Grundsätzliches <?php $di = new ZendDiDi(); $service = $di->get('AcmeTalkService'); var_dump($service); $service2 = $di->get('AcmeTalkService'); var_dump($service2); // gleiche Instanz wie $service $service3 = $di->get( 'AcmeTalkService', array( 'repo' => new phpbnl12TalkRepository() ) ); var_dump($service3); // neue Instanz
  • 72. Real World Dependency Injection – Special Edition ZendDi – Builder Definition <?php // Dependency beschreiben $dep = new ZendDiDefinitionBuilderPhpClass(); $dep->setName('AcmeTalkRepository'); // Klasse beschreiben $class = new ZendDiDefinitionBuilderPhpClass(); $class->setName('AcmeTalkService'); // Injection Methode beschreiben $im = new ZendDiDefinitionBuilderInjectionMethod(); $im->setName('__construct'); $im->addParameter('repo', 'AcmeTalkRepository'); $class->addInjectionMethod($im); // Builder konfigurieren $builder = new ZendDiDefinitionBuilderDefinition(); $builder->addClass($dep); $builder->addClass($class);
  • 73. Real World Dependency Injection – Special Edition ZendDi – Builder Definition <?php // zur DefinitionList hinzufügen $defList = new ZendDiDefinitionList($builder); $di = new ZendDiDi($defList); $service = $di->get('AcmeTalkService'); var_dump($service);
  • 74. Real World Dependency Injection – Special Edition
  • 75. Real World Dependency Injection – Special Edition Symfony2 <?php namespace AcmeTalkBundleController; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationTemplate; class TalkController extends Controller { /** * @Route("/", name="_talk") * @Template() */ public function indexAction() { $service = $this->get('acme.talk.service'); return array(); } }
  • 76. Real World Dependency Injection – Special Edition Symfony2 – Konfigurationsdatei Datei services.xml in src/Acme/DemoBundle/Resources/config <?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"> </container>
  • 77. Real World Dependency Injection – Special Edition Symfony2 – Constructor 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="AcmeTalkBundleServiceTalkRepository" /> <service id="acme.talk.service" class="AcmeTalkBundleServiceTalkService"> <argument type="service" id="acme.talk.repo" /> </service> </services> </container>
  • 78. Real World Dependency Injection – Special Edition Symfony2 – Setter 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="AcmeTalkBundleServiceLogger" /> <service id="acme.talk.repo" class="AcmeTalkBundleServiceTalkRepository" /> <service id="acme.talk.service" class="AcmeTalkBundleServiceTalkService"> <argument type="service" id="acme.talk.repo" /> <call method="setLogger"> <argument type="service" id="acme.talk.logger" /> </call> </service> </services> </container>
  • 79. Real World Dependency Injection – Special Edition Symfony2 – Setter Injection (optional) <?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="AcmeTalkBundleServiceLogger" /> <service id="acme.talk.repo" class="AcmeTalkBundleServiceTalkRepository" /> <service id="acme.talk.service" class="AcmeTalkBundleServiceTalkService"> <argument type="service" id="acme.talk.repo" /> <call method="setLogger"> <argument type="service" id="acme.talk.logger" on-invalid="ignore" /> </call> </service> </services> </container>
  • 80. Real World Dependency Injection – Special Edition Symfony2 – Property 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="AcmeTalkBundleServiceTalkRepository" /> <service id="acme.talk.service" class="AcmeTalkBundleServiceTalkService"> <property name="talkRepository" type="service" id="acme.talk.repo" /> </service> </services> </container>
  • 81. Real World Dependency Injection – Special Edition Symfony2 – private / öffentliche Services <?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="AcmeTalkBundleServiceLogger" public="false" /> <service id="acme.talk.repo" class="AcmeTalkBundleServiceTalkRepository" /> <service id="acme.talk.service" class="AcmeTalkBundleServiceTalkService"> <argument type="service" id="acme.talk.repo" /> <call method="setLogger"> <argument type="service" id="acme.talk.logger" /> </call> </service> </services> </container>
  • 82. Real World Dependency Injection – Special Edition Symfony2 – Vererbung <?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="AcmeTalkBundleServiceTalkService" 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>
  • 83. Real World Dependency Injection – Special Edition Symfony2 – Scoping <?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="AcmeTalkBundleServiceTalkRepository" /> <service id="acme.talk.service" class="AcmeTalkBundleServiceTalkService" scope="prototype"> <property name="talkRepository" type="service" id="acme.talk.repo" /> </service> </services> </container>
  • 84. Real World Dependency Injection – Special Edition
  • 85. Real World Dependency Injection – Special Edition Flow3 – Constructor Injection <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkServiceInterface */ protected $talkService; public function __construct( AcmeDemoServiceTalkService $talkService) { $this->talkService = $talkService; } public function indexAction() { } }
  • 86. Real World Dependency Injection – Special Edition Flow3 – Setter Injection (manuell) <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkServiceInterface */ protected $talkService; public function setTalkService( AcmeDemoServiceTalkService $talkService) { $this->talkService = $talkService; } public function indexAction() { } }
  • 87. Real World Dependency Injection – Special Edition Flow3 – Setter Injection (manuell) Datei Objects.yaml in Packages/Application/Acme.Demo/Configuration # @package Acme AcmeDemoControllerStandardController: properties: talkService: object: AcmeDemoServiceTalkService
  • 88. Real World Dependency Injection – Special Edition Flow3 – Setter Injection (automatisch) <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkServiceInterface */ protected $talkService; public function injectTalkService( AcmeDemoServiceTalkService $talkService) { $this->talkService = $talkService; } public function indexAction() { } }
  • 89. Real World Dependency Injection – Special Edition Flow3 – Setter Injection (automatisch) <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkServiceInterface */ protected $talkService; public function injectSomethingElse( AcmeDemoServiceTalkService $talkService) { $this->talkService = $talkService; } public function indexAction() { } }
  • 90. Real World Dependency Injection – Special Edition Flow3 – Property Injection <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkService * @FLOW3Inject */ protected $talkService; public function indexAction() { } }
  • 91. Real World Dependency Injection – Special Edition Flow3 – Property Injection (mittels Interface) <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkServiceInterface * @FLOW3Inject */ protected $talkService; public function indexAction() { } }
  • 92. Real World Dependency Injection – Special Edition Flow3 – Property Injection (mittels Interface) Datei Objects.yaml in Packages/Application/Acme.Demo/Configuration # @package Acme AcmeDemoServiceTalkServiceInterface: className: 'AcmeDemoServiceTalkService'
  • 93. Real World Dependency Injection – Special Edition Flow3 – Scoping <?php namespace AcmeDemoController; use TYPO3FLOW3Annotations as FLOW3; /** * @FLOW3Scope("session") */ class StandardController extends TYPO3FLOW3MVCControllerActionController { /** * @var AcmeDemoServiceTalkServiceInterface * @FLOW3Inject */ protected $talkService; public function indexAction() { } }
  • 94. Real World Dependency Injection – Special Edition Vorteile
  • 95. Real World Dependency Injection – Special Edition Vorteile Lose Kopplung, gesteigerte Wiederverwendbarkeit !
  • 96. Real World Dependency Injection – Special Edition Vorteile Codeumfang reduzieren, Fokus auf das Wesentliche!
  • 97. Real World Dependency Injection – Special Edition Vorteile Hilft Entwicklern den Code besser zu verstehen!
  • 98. Real World Dependency Injection – Special Edition Nachteil – Kein JSR330 für PHP Bucket, Crafty, FLOW3, Imind_Context, PicoContainer, Pimple, Phemto, Stubbles, Symfony 2.0, Sphicy, Solar, Substrate, XJConf, Yadif, ZendDi , Lion Framework, Spiral Framework, Xyster Framework, …
  • 99. Real World Dependency Injection – Special Edition Nachteil – Entwickler müssen umdenken Konfiguration ↔ Laufzeit
  • 100. Real World Dependency Injection – Special Edition Nachteil – Keine IDE Unterstützung!