SlideShare a Scribd company logo
27 марта 2010 г.
                                     Санкт-Петербург




   Dependency Injection
(Внедрение Зависимостей)
ZF, Zend_Application, DI Container, Symfony DI
О Докладчике

Кирилл Чебунин
• Ведущий PHP разработчик Equelli, ltd.
• Около 4 лет опыта PHP
• Более 2х лет использования ZendFramework
Выбор классов

• Адаптеры
• Плагины/Хелперы
• Интерфейсы и Реализация
Хранилище
$GLOBALS
$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('/var/log/myapp.log');
$logger->addWriter($writer);

$GLOBALS['log'] = $logger;

class UserController extends Zend_Controller_Action
{
   public function indexAction()
   {
     /* @var $log Zend_Log */
     $log = $GLOBALS['log'];
     $log->log('Index Action', Zend_Log::INFO);
   }

    public function secondAction()
    {
      /* @var $log Zend_Log */
      $log = $GLOBALS['log'];
      $log->log('Second Action', Zend_Log::INFO);
    }

}
Zend_Registry
$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('/var/log/myapp.log');
$logger->addWriter($writer);

Zend_Registry::set('log', $logger);

class UserController extends Zend_Controller_Action
{
   public function indexAction()
   {
     /* @var $log Zend_Log */
     $log = Zend_Registry::get('log');
     $log->log('Index Action', Zend_Log::INFO);
   }

    public function secondAction()
    {
      /* @var $log Zend_Log */
      $log = Zend_Registry::get('log');
      $log->log('Second Action', Zend_Log::INFO);
    }

}
Zend_Application

[production]
resources.log.file.writerName = "Stream"
resources.log.file.writerParams.stream = "/var/log/myapp.log"

class UserController extends Zend_Controller_Action
{
   public function indexAction()
   {
     /* @var $log Zend_Log */
     $log = $this->getInvokeArg('bootstrap')->getResource('log');
     $log->log('Index Action', Zend_Log::INFO);
   }

    public function secondAction()
    {
      /* @var $log Zend_Log */
      $log = $this->getInvokeArg('bootstrap')->getResource('log');
      $log->log('Second Action', Zend_Log::INFO);
    }

}
Zend_Application
      & Dependency Injection
           class My_Application_Resource_Service_UserService
              extends Zend_Application_Resource_ResourceAbstract
           {
              //[.....]
           }

           class My_Application_Resource_Service_PostService
              extends Zend_Application_Resource_ResourceAbstract
           {
              //[.....]
           }

           class My_Application_Resource_Service_ArticleService
              extends Zend_Application_Resource_ResourceAbstract
           {
              //[.....]
           }

           class My_Application_Resource_Service_RoleService
               extends Zend_Application_Resource_ResourceAbstract
           {
               //[.....]
           }
           //[.....]
           //[.....]
           //[.....]
Zend_Application
      & Dependency Injection
           class Zend_Application_Resource_Log
              extends Zend_Application_Resource_ResourceAbstract
           {
              //[.....]
              /**
               * Defined by Zend_Application_Resource_Resource
               *
               * @return Zend_Log
               */
              public function init()
              {
                  return $this->getLog();
              }

               //[.....]

               public function getLog()
               {
                 if (null === $this->_log) {
                     $options = $this->getOptions();
                     $log = Zend_Log::factory($options);
                     $this->setLog($log);
                 }
                 return $this->_log;
               }
           }
Конфигурация вместо кода

<service id="log" class="Zend_Log" constructor="factory">
     <argument type="collection">
          <argument key="file" type="collection">
               <argument key="writerName">Stream</argument>
               <argument key="writerParams" type="collection">
                     <argument key="stream">/var/log/myapp.log</argument>
               </argument>
          </argument>
     </argument>
</service>

<service id="log" class="Zend_Log">
     <call method="addWriter">
           <argument type="service">
                <service class="Zend_Log_Writer_Stream">
                     <argument>/var/log/myapp.log</argument>
                </service>
           </argument>
     </call>
</service>
Dependency Injection —
      A specific form of Inversion of Control (IOC)



Внедрение зависимости —
     Специфическая форма «обращения контроля»




                                 Взято из ®Wikipedia, the free encyclopedia
Inversion Of Control (IOC)
PHP DI Containers

•   Symfony Dependency Injection
•   Yadif_Container
•   Seasar DI Container (S2Container)
•   Phemto
•   Xyster_Container
•   TYPO3
• ...........
Symfony DI Container

•   Поддержка XML, YAML, PHP и INI конфигураций
•   Ленивая загрузка
•   Constructor and Method Injection
•   Shared/NotShared ресурсы
•   Конфигураторы
•   Алиасы
Замена контейнера

require_once 'Zend/Application.php';
require_once 'sfServiceContainerBuilder.php';
require_once 'sfServiceContainerLoaderFileXml.php';

//Create Container and load configuration from file
$container = new sfServiceContainerBuilder();
$loader = new sfServiceContainerLoaderFileXml($container);
$loader->load(APPLICATION_PATH . '/configs/dependencies.xml');

// Create application, bootstrap, and run
$application = new Zend_Application(
   APPLICATION_ENV,
   APPLICATION_PATH . '/configs/application.ini'
);
$application->getBootstrap()->setContainer($container);
$application->bootstrap()
        ->run();
Dependencies.xml
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony-project.org/2.0/container">

     <services>
       <service id="userMapper" class="UserMapperImpl"/>
          <service id="PostMapper" class="PostMapperImpl"/>
          <service id="CommentMapper" class="CommentMapperImpl" />

          <service id="postService" class="PostServiceImpl">
               <call method="setUserMapper">
                     <argument type="service" id="userMapper" />
               </call>
               <call method="setPostMapper">
                     <argument type="service" id="postMapper" />
               </call>
               <call method="setCommentMapper">
                     <argument type="service" id="commentMapper" />
               </call>
          </service>

          <service id="userService" class="UserServiceImpl">
               <call method="setUserMapper">
                     <argument type="service" id="userMapper" />
               </call>
          </service>
     </services>

</container>
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
//[..................]
/**
  * Inject properties on Pre-Dispatch
  */
public function preDispatch()
{
        $actionController = $this->getActionController();

     $class = new Zend_Reflection_Class($actionController);
     $properties = $class->getProperties();

     /* @var $property Zend_Reflection_Property */
     foreach ($properties as $property) {
          if ($property->getDocComment()->hasTag('Inject')) {
                $injectTag = $property->getDocComment()->getTag('Inject');
                $serviceName = $injectTag->getDescription();

                if (empty($serviceName)) {
                      $serviceName = $this->_formatServiceName(
                           $property->getName());
                }

                if (isset($this->_сontainer->$serviceName)) {
                       $this->_injectProperty(
                            $property,
                            $this->_container->$serviceName
                       );
                }
          }
     }

}
Инъекция через аннотации
class UserController extends Zend_Controller_Action
{
   /**
    * Logger
    * @var Zend_Log
    * @Inject
    */
   private $_log;

    public function setLog($log)
    {
      $this->_log = $log;
    }

    public function indexAction()
    {
      $this->_log->log('Index Action', Zend_Log::INFO);
    }

    public function secondAction()
    {
      $this->_log->log('Second Action', Zend_Log::INFO);
    }

}
Проблемы, советы, размышления


  Транзакции, сквозная функциональность
Транзакции


• Транзакции недоступны в сервисном слое в
  нашей реализации
• Транзакции это уровень сервисов.
• Может быть несколько источников данных.
Общий интерфейс транзакций

interface TransactionManager
{
   /**
    * Start a new transaction
    * @return unknown_type
    */
   public function beginTransaction();

    /**
     * Commit the current transaction
     * @return unknown_type
     */
    public function commit();

    /**
     * Rollback the current transcation
     * @return unknown_type
     */
    public function rollback();

}
Использование нескольких
                 менеджеров транзакций
class MultipleTransactionManager implements TransactionManager
{
   private $tms = array();

    public function setTransactionManagers(array $tms)
    {
      $this->tms = $tms;
      return $this;
    }

    public function beginTransaction()
    {
      /* @var $tm TransactionManager */
      foreach ($this->tms as $tm) {
         $tm->beginTransaction();
      }
    }

    //[.....]

}
Сквозная функциональность
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
Аспектно-ориентированное
 программирование (АОП)
Динамические прокси

class SomeClass
{
   public function someMethod() {}
}

class __GeneratedDynamicProxy__ extends SomeClass
{
   private $proxyManager;

    public function someMethod()
    {
      return $this->proxyManager->invoke(new ReflectionMethod(
          get_parent_class($this),
          __FUNCTION__
      ));
    }
}
Добавим Аннотаций

public function someMethod()                           /**
{                                                        * Some business method
  $this->log(__METHOD__ . ' start');                     * @Transactional
  if ($this->user->role != 'ROLE_ADMIN') {               * @Log
      throw new SecuredException($this->user->role);     * @Secured ROLE_ADMIN
  }                                                      */
  $tm = $this->tm;                                     public function someMethod()
  $tm->beginTransaction();                             {
  try {                                                    doBusiness();
      doBusiness();                                    }
      $tm->commit();
  } catch (Exception $e) {
      $tm->rollback();
      throw $e;
  }
  $this->log(__METHOD__ . ' end');
}
Хорошая архитектура —
        Простота конфигурации
<service id="actionHelperStack"
     class="Zend_Controller_Action_HelperBroker"
     constructor="getStack">
  <call method="push">
     <argument type="service">
          <service class="Zend_Controller_Action_Helper_ViewRenderer">
               <argument type="service" id="view"/>
          </service>
     </argument>
  </call>
  <call method="push">
     <argument type="service">
          <service class="My_Controller_Action_Helper_DI"/>
     </argument>
  </call>
</service>

More Related Content

PDF
Rich Model And Layered Architecture in SF2 Application
PDF
Your Entity, Your Code
ODP
Symfony2, creare bundle e valore per il cliente
PDF
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
ODP
Rich domain model with symfony 2.5 and doctrine 2.5
PPTX
Adding Dependency Injection to Legacy Applications
PDF
Decoupling with Design Patterns and Symfony2 DIC
PDF
Introduction to Zend Framework web services
Rich Model And Layered Architecture in SF2 Application
Your Entity, Your Code
Symfony2, creare bundle e valore per il cliente
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Rich domain model with symfony 2.5 and doctrine 2.5
Adding Dependency Injection to Legacy Applications
Decoupling with Design Patterns and Symfony2 DIC
Introduction to Zend Framework web services

What's hot (20)

PDF
The IoC Hydra
PDF
The IoC Hydra - Dutch PHP Conference 2016
PDF
Design Patterns avec PHP 5.3, Symfony et Pimple
PDF
Min-Maxing Software Costs
PDF
Symfony World - Symfony components and design patterns
KEY
Symfony2 Building on Alpha / Beta technology
PDF
Silex meets SOAP & REST
PDF
Beyond symfony 1.2 (Symfony Camp 2008)
PDF
購物車程式架構簡介
PDF
Min-Maxing Software Costs - Laracon EU 2015
PDF
Design how your objects talk through mocking
PDF
Decoupling the Ulabox.com monolith. From CRUD to DDD
PDF
PHP 5.3 and Lithium: the most rad php framework
ODP
PHPUnit elevato alla Symfony2
PDF
Database Design Patterns
PDF
The History of PHPersistence
PDF
Drupal Field API. Practical usage
PDF
Sylius and Api Platform The story of integration
PDF
The Zen of Lithium
PPTX
Speed up your developments with Symfony2
The IoC Hydra
The IoC Hydra - Dutch PHP Conference 2016
Design Patterns avec PHP 5.3, Symfony et Pimple
Min-Maxing Software Costs
Symfony World - Symfony components and design patterns
Symfony2 Building on Alpha / Beta technology
Silex meets SOAP & REST
Beyond symfony 1.2 (Symfony Camp 2008)
購物車程式架構簡介
Min-Maxing Software Costs - Laracon EU 2015
Design how your objects talk through mocking
Decoupling the Ulabox.com monolith. From CRUD to DDD
PHP 5.3 and Lithium: the most rad php framework
PHPUnit elevato alla Symfony2
Database Design Patterns
The History of PHPersistence
Drupal Field API. Practical usage
Sylius and Api Platform The story of integration
The Zen of Lithium
Speed up your developments with Symfony2
Ad

Viewers also liked (20)

PDF
TDR prezentacija - Press konferencija Beograd 19.03.13
PDF
Hardoon Image Ranking With Implicit Feedback From Eye Movements
RTF
Photography
PDF
Detailed Concept Presentation
RTF
filming plan
PPT
การจัดการเรียนภาษาอังกฤษ
PPTX
Eidea_SEMCOM
PDF
F2F 2015 - Client SDK (Specific Plataform Android)
PPT
TEMA 3B SER and ESTAR
PPT
Tools for Learning (51.-60.)
PDF
แบบนำเสนอผลงานวิชาการ
PDF
Kinnunen Towards Task Independent Person Authentication Using Eye Movement Si...
PDF
תכירו את שולה הישנה והחדשה
PPTX
Web api
PDF
Acta ci 150910
PDF
Acta asamblea eroski vigo
PDF
Canosa Saliency Based Decision Support
PPSX
Konkurs
PDF
Protocolo carrefour
TDR prezentacija - Press konferencija Beograd 19.03.13
Hardoon Image Ranking With Implicit Feedback From Eye Movements
Photography
Detailed Concept Presentation
filming plan
การจัดการเรียนภาษาอังกฤษ
Eidea_SEMCOM
F2F 2015 - Client SDK (Specific Plataform Android)
TEMA 3B SER and ESTAR
Tools for Learning (51.-60.)
แบบนำเสนอผลงานวิชาการ
Kinnunen Towards Task Independent Person Authentication Using Eye Movement Si...
תכירו את שולה הישנה והחדשה
Web api
Acta ci 150910
Acta asamblea eroski vigo
Canosa Saliency Based Decision Support
Konkurs
Protocolo carrefour
Ad

Similar to ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection) (20)

PDF
Symfony2 from the Trenches
PDF
ZF2 for the ZF1 Developer
PDF
Symfony2 - from the trenches
KEY
Zend framework service
KEY
Zend framework service
PDF
Unit testing after Zend Framework 1.8
PDF
Zend Framework 2 - Basic Components
PDF
WordPress REST API hacking
PDF
Doctrine For Beginners
PPT
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
PDF
How I started to love design patterns
KEY
Zend Framework Study@Tokyo #2
PDF
Dependency Injection
PDF
Dependency injection in Drupal 8
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
PDF
How Kris Writes Symfony Apps
PPTX
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
PPTX
Domain Driven Design using Laravel
PPT
Easy rest service using PHP reflection api
PDF
Migrare da symfony 1 a Symfony2
Symfony2 from the Trenches
ZF2 for the ZF1 Developer
Symfony2 - from the trenches
Zend framework service
Zend framework service
Unit testing after Zend Framework 1.8
Zend Framework 2 - Basic Components
WordPress REST API hacking
Doctrine For Beginners
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
How I started to love design patterns
Zend Framework Study@Tokyo #2
Dependency Injection
Dependency injection in Drupal 8
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
How Kris Writes Symfony Apps
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
Domain Driven Design using Laravel
Easy rest service using PHP reflection api
Migrare da symfony 1 a Symfony2

More from ZFConf Conference (20)

PPTX
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
PPT
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
PDF
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
PDF
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
PPTX
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
PDF
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
PDF
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ODP
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
PPT
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
PPTX
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
PPTX
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
PPT
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
PDF
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
PPT
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
PPT
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ODP
ZFConf 2010: Zend Framework and Doctrine
PPT
ZFConf 2010: History of e-Shtab.ru
PPTX
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
PPT
ZFConf 2010: Performance of Zend Framework Applications
PPTX
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: History of e-Shtab.ru
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)

ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)

  • 1. 27 марта 2010 г. Санкт-Петербург Dependency Injection (Внедрение Зависимостей) ZF, Zend_Application, DI Container, Symfony DI
  • 2. О Докладчике Кирилл Чебунин • Ведущий PHP разработчик Equelli, ltd. • Около 4 лет опыта PHP • Более 2х лет использования ZendFramework
  • 3. Выбор классов • Адаптеры • Плагины/Хелперы • Интерфейсы и Реализация
  • 5. $GLOBALS $logger = new Zend_Log(); $writer = new Zend_Log_Writer_Stream('/var/log/myapp.log'); $logger->addWriter($writer); $GLOBALS['log'] = $logger; class UserController extends Zend_Controller_Action { public function indexAction() { /* @var $log Zend_Log */ $log = $GLOBALS['log']; $log->log('Index Action', Zend_Log::INFO); } public function secondAction() { /* @var $log Zend_Log */ $log = $GLOBALS['log']; $log->log('Second Action', Zend_Log::INFO); } }
  • 6. Zend_Registry $logger = new Zend_Log(); $writer = new Zend_Log_Writer_Stream('/var/log/myapp.log'); $logger->addWriter($writer); Zend_Registry::set('log', $logger); class UserController extends Zend_Controller_Action { public function indexAction() { /* @var $log Zend_Log */ $log = Zend_Registry::get('log'); $log->log('Index Action', Zend_Log::INFO); } public function secondAction() { /* @var $log Zend_Log */ $log = Zend_Registry::get('log'); $log->log('Second Action', Zend_Log::INFO); } }
  • 7. Zend_Application [production] resources.log.file.writerName = "Stream" resources.log.file.writerParams.stream = "/var/log/myapp.log" class UserController extends Zend_Controller_Action { public function indexAction() { /* @var $log Zend_Log */ $log = $this->getInvokeArg('bootstrap')->getResource('log'); $log->log('Index Action', Zend_Log::INFO); } public function secondAction() { /* @var $log Zend_Log */ $log = $this->getInvokeArg('bootstrap')->getResource('log'); $log->log('Second Action', Zend_Log::INFO); } }
  • 8. Zend_Application & Dependency Injection class My_Application_Resource_Service_UserService extends Zend_Application_Resource_ResourceAbstract { //[.....] } class My_Application_Resource_Service_PostService extends Zend_Application_Resource_ResourceAbstract { //[.....] } class My_Application_Resource_Service_ArticleService extends Zend_Application_Resource_ResourceAbstract { //[.....] } class My_Application_Resource_Service_RoleService extends Zend_Application_Resource_ResourceAbstract { //[.....] } //[.....] //[.....] //[.....]
  • 9. Zend_Application & Dependency Injection class Zend_Application_Resource_Log extends Zend_Application_Resource_ResourceAbstract { //[.....] /** * Defined by Zend_Application_Resource_Resource * * @return Zend_Log */ public function init() { return $this->getLog(); } //[.....] public function getLog() { if (null === $this->_log) { $options = $this->getOptions(); $log = Zend_Log::factory($options); $this->setLog($log); } return $this->_log; } }
  • 10. Конфигурация вместо кода <service id="log" class="Zend_Log" constructor="factory"> <argument type="collection"> <argument key="file" type="collection"> <argument key="writerName">Stream</argument> <argument key="writerParams" type="collection"> <argument key="stream">/var/log/myapp.log</argument> </argument> </argument> </argument> </service> <service id="log" class="Zend_Log"> <call method="addWriter"> <argument type="service"> <service class="Zend_Log_Writer_Stream"> <argument>/var/log/myapp.log</argument> </service> </argument> </call> </service>
  • 11. Dependency Injection — A specific form of Inversion of Control (IOC) Внедрение зависимости — Специфическая форма «обращения контроля» Взято из ®Wikipedia, the free encyclopedia
  • 13. PHP DI Containers • Symfony Dependency Injection • Yadif_Container • Seasar DI Container (S2Container) • Phemto • Xyster_Container • TYPO3 • ...........
  • 14. Symfony DI Container • Поддержка XML, YAML, PHP и INI конфигураций • Ленивая загрузка • Constructor and Method Injection • Shared/NotShared ресурсы • Конфигураторы • Алиасы
  • 15. Замена контейнера require_once 'Zend/Application.php'; require_once 'sfServiceContainerBuilder.php'; require_once 'sfServiceContainerLoaderFileXml.php'; //Create Container and load configuration from file $container = new sfServiceContainerBuilder(); $loader = new sfServiceContainerLoaderFileXml($container); $loader->load(APPLICATION_PATH . '/configs/dependencies.xml'); // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->getBootstrap()->setContainer($container); $application->bootstrap() ->run();
  • 16. Dependencies.xml <?xml version="1.0" encoding="UTF-8"?> <container xmlns="http://symfony-project.org/2.0/container"> <services> <service id="userMapper" class="UserMapperImpl"/> <service id="PostMapper" class="PostMapperImpl"/> <service id="CommentMapper" class="CommentMapperImpl" /> <service id="postService" class="PostServiceImpl"> <call method="setUserMapper"> <argument type="service" id="userMapper" /> </call> <call method="setPostMapper"> <argument type="service" id="postMapper" /> </call> <call method="setCommentMapper"> <argument type="service" id="commentMapper" /> </call> </service> <service id="userService" class="UserServiceImpl"> <call method="setUserMapper"> <argument type="service" id="userMapper" /> </call> </service> </services> </container>
  • 18. //[..................] /** * Inject properties on Pre-Dispatch */ public function preDispatch() { $actionController = $this->getActionController(); $class = new Zend_Reflection_Class($actionController); $properties = $class->getProperties(); /* @var $property Zend_Reflection_Property */ foreach ($properties as $property) { if ($property->getDocComment()->hasTag('Inject')) { $injectTag = $property->getDocComment()->getTag('Inject'); $serviceName = $injectTag->getDescription(); if (empty($serviceName)) { $serviceName = $this->_formatServiceName( $property->getName()); } if (isset($this->_сontainer->$serviceName)) { $this->_injectProperty( $property, $this->_container->$serviceName ); } } } }
  • 19. Инъекция через аннотации class UserController extends Zend_Controller_Action { /** * Logger * @var Zend_Log * @Inject */ private $_log; public function setLog($log) { $this->_log = $log; } public function indexAction() { $this->_log->log('Index Action', Zend_Log::INFO); } public function secondAction() { $this->_log->log('Second Action', Zend_Log::INFO); } }
  • 20. Проблемы, советы, размышления Транзакции, сквозная функциональность
  • 21. Транзакции • Транзакции недоступны в сервисном слое в нашей реализации • Транзакции это уровень сервисов. • Может быть несколько источников данных.
  • 22. Общий интерфейс транзакций interface TransactionManager { /** * Start a new transaction * @return unknown_type */ public function beginTransaction(); /** * Commit the current transaction * @return unknown_type */ public function commit(); /** * Rollback the current transcation * @return unknown_type */ public function rollback(); }
  • 23. Использование нескольких менеджеров транзакций class MultipleTransactionManager implements TransactionManager { private $tms = array(); public function setTransactionManagers(array $tms) { $this->tms = $tms; return $this; } public function beginTransaction() { /* @var $tm TransactionManager */ foreach ($this->tms as $tm) { $tm->beginTransaction(); } } //[.....] }
  • 27. Динамические прокси class SomeClass { public function someMethod() {} } class __GeneratedDynamicProxy__ extends SomeClass { private $proxyManager; public function someMethod() { return $this->proxyManager->invoke(new ReflectionMethod( get_parent_class($this), __FUNCTION__ )); } }
  • 28. Добавим Аннотаций public function someMethod() /** { * Some business method $this->log(__METHOD__ . ' start'); * @Transactional if ($this->user->role != 'ROLE_ADMIN') { * @Log throw new SecuredException($this->user->role); * @Secured ROLE_ADMIN } */ $tm = $this->tm; public function someMethod() $tm->beginTransaction(); { try { doBusiness(); doBusiness(); } $tm->commit(); } catch (Exception $e) { $tm->rollback(); throw $e; } $this->log(__METHOD__ . ' end'); }
  • 29. Хорошая архитектура — Простота конфигурации <service id="actionHelperStack" class="Zend_Controller_Action_HelperBroker" constructor="getStack"> <call method="push"> <argument type="service"> <service class="Zend_Controller_Action_Helper_ViewRenderer"> <argument type="service" id="view"/> </service> </argument> </call> <call method="push"> <argument type="service"> <service class="My_Controller_Action_Helper_DI"/> </argument> </call> </service>