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

What's hot (20)

PDF
The IoC Hydra
Kacper Gunia
 
PDF
The IoC Hydra - Dutch PHP Conference 2016
Kacper Gunia
 
PDF
Design Patterns avec PHP 5.3, Symfony et Pimple
Hugo Hamon
 
PDF
Min-Maxing Software Costs
Konstantin Kudryashov
 
PDF
Symfony World - Symfony components and design patterns
Łukasz Chruściel
 
KEY
Symfony2 Building on Alpha / Beta technology
Daniel Knell
 
PDF
Silex meets SOAP & REST
Hugo Hamon
 
PDF
Beyond symfony 1.2 (Symfony Camp 2008)
Fabien Potencier
 
PDF
購物車程式架構簡介
Jace Ju
 
PDF
Min-Maxing Software Costs - Laracon EU 2015
Konstantin Kudryashov
 
PDF
Design how your objects talk through mocking
Konstantin Kudryashov
 
PDF
Decoupling the Ulabox.com monolith. From CRUD to DDD
Aleix Vergés
 
PDF
PHP 5.3 and Lithium: the most rad php framework
G Woo
 
ODP
PHPUnit elevato alla Symfony2
eugenio pombi
 
PDF
Database Design Patterns
Hugo Hamon
 
PDF
The History of PHPersistence
Hugo Hamon
 
PDF
Drupal Field API. Practical usage
Pavel Makhrinsky
 
PDF
Sylius and Api Platform The story of integration
Łukasz Chruściel
 
PDF
The Zen of Lithium
Nate Abele
 
PPTX
Speed up your developments with Symfony2
Hugo Hamon
 
The IoC Hydra
Kacper Gunia
 
The IoC Hydra - Dutch PHP Conference 2016
Kacper Gunia
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Hugo Hamon
 
Min-Maxing Software Costs
Konstantin Kudryashov
 
Symfony World - Symfony components and design patterns
Łukasz Chruściel
 
Symfony2 Building on Alpha / Beta technology
Daniel Knell
 
Silex meets SOAP & REST
Hugo Hamon
 
Beyond symfony 1.2 (Symfony Camp 2008)
Fabien Potencier
 
購物車程式架構簡介
Jace Ju
 
Min-Maxing Software Costs - Laracon EU 2015
Konstantin Kudryashov
 
Design how your objects talk through mocking
Konstantin Kudryashov
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Aleix Vergés
 
PHP 5.3 and Lithium: the most rad php framework
G Woo
 
PHPUnit elevato alla Symfony2
eugenio pombi
 
Database Design Patterns
Hugo Hamon
 
The History of PHPersistence
Hugo Hamon
 
Drupal Field API. Practical usage
Pavel Makhrinsky
 
Sylius and Api Platform The story of integration
Łukasz Chruściel
 
The Zen of Lithium
Nate Abele
 
Speed up your developments with Symfony2
Hugo Hamon
 

Viewers also liked (20)

PDF
TDR prezentacija - Press konferencija Beograd 19.03.13
TDR d.o.o Rovinj
 
PDF
Hardoon Image Ranking With Implicit Feedback From Eye Movements
Kalle
 
RTF
Photography
Katherine Brittain
 
PDF
Detailed Concept Presentation
Yoomi Lee
 
RTF
filming plan
Katherine Brittain
 
PPT
การจัดการเรียนภาษาอังกฤษ
Thanasukarn Bhat
 
PPTX
Eidea_SEMCOM
Ronak Thakkar
 
PDF
F2F 2015 - Client SDK (Specific Plataform Android)
Daniel Passos
 
PPT
TEMA 3B SER and ESTAR
SenoraAmandaWhite
 
PPT
Tools for Learning (51.-60.)
nazzzy
 
PDF
แบบนำเสนอผลงานวิชาการ
Princess Chulabhorn's College, Chiang Rai Thailand
 
PDF
Kinnunen Towards Task Independent Person Authentication Using Eye Movement Si...
Kalle
 
PDF
תכירו את שולה הישנה והחדשה
haimkarel
 
PPTX
Web api
udaiappa
 
PDF
Acta ci 150910
oscargaliza
 
PDF
Acta asamblea eroski vigo
oscargaliza
 
PDF
Canosa Saliency Based Decision Support
Kalle
 
PPSX
Konkurs
guest895d8bd
 
PDF
Protocolo carrefour
oscargaliza
 
TDR prezentacija - Press konferencija Beograd 19.03.13
TDR d.o.o Rovinj
 
Hardoon Image Ranking With Implicit Feedback From Eye Movements
Kalle
 
Photography
Katherine Brittain
 
Detailed Concept Presentation
Yoomi Lee
 
filming plan
Katherine Brittain
 
การจัดการเรียนภาษาอังกฤษ
Thanasukarn Bhat
 
Eidea_SEMCOM
Ronak Thakkar
 
F2F 2015 - Client SDK (Specific Plataform Android)
Daniel Passos
 
TEMA 3B SER and ESTAR
SenoraAmandaWhite
 
Tools for Learning (51.-60.)
nazzzy
 
แบบนำเสนอผลงานวิชาการ
Princess Chulabhorn's College, Chiang Rai Thailand
 
Kinnunen Towards Task Independent Person Authentication Using Eye Movement Si...
Kalle
 
תכירו את שולה הישנה והחדשה
haimkarel
 
Web api
udaiappa
 
Acta ci 150910
oscargaliza
 
Acta asamblea eroski vigo
oscargaliza
 
Canosa Saliency Based Decision Support
Kalle
 
Konkurs
guest895d8bd
 
Protocolo carrefour
oscargaliza
 
Ad

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

PPT
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
Kirill Chebunin
 
PDF
Zend Framework 2 - Basic Components
Mateusz Tymek
 
PDF
ZF2 for the ZF1 Developer
Gary Hockin
 
PDF
Symfony2 from the Trenches
Jonathan Wage
 
DOCX
Zend framework 2.0
shrutisgupta
 
PDF
Symfony2 - from the trenches
Lukas Smith
 
ODP
Dependency Injection, Zend Framework and Symfony Container
Diego Lewin
 
PDF
Zend Framework 2 Patterns
Zend by Rogue Wave Software
 
PDF
Zend Framework 2 quick start
Enrico Zimuel
 
PDF
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf Conference
 
PDF
A quick start on Zend Framework 2
Enrico Zimuel
 
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
James Titcumb
 
PPTX
Zf2 phpquebec
mkherlakian
 
PDF
Zend Framework 1 + Doctrine 2
Ralph Schindler
 
PDF
symfony on action - WebTech 207
patter
 
PDF
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
James Titcumb
 
PPTX
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf Conference
 
PPT
Zend Framework
Hao Chen 陈浩
 
PDF
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
James Titcumb
 
PDF
Models Best Practices (ZF MVC)
eddiejaoude
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
Kirill Chebunin
 
Zend Framework 2 - Basic Components
Mateusz Tymek
 
ZF2 for the ZF1 Developer
Gary Hockin
 
Symfony2 from the Trenches
Jonathan Wage
 
Zend framework 2.0
shrutisgupta
 
Symfony2 - from the trenches
Lukas Smith
 
Dependency Injection, Zend Framework and Symfony Container
Diego Lewin
 
Zend Framework 2 Patterns
Zend by Rogue Wave Software
 
Zend Framework 2 quick start
Enrico Zimuel
 
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf Conference
 
A quick start on Zend Framework 2
Enrico Zimuel
 
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
James Titcumb
 
Zf2 phpquebec
mkherlakian
 
Zend Framework 1 + Doctrine 2
Ralph Schindler
 
symfony on action - WebTech 207
patter
 
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
James Titcumb
 
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf Conference
 
Zend Framework
Hao Chen 陈浩
 
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
James Titcumb
 
Models Best Practices (ZF MVC)
eddiejaoude
 
Ad

More from ZFConf Conference (20)

PPTX
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf Conference
 
PPT
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf Conference
 
PDF
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf Conference
 
PDF
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf Conference
 
PDF
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf Conference
 
ODP
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf Conference
 
PPT
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf Conference
 
PPTX
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf Conference
 
PPTX
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf Conference
 
PPT
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf Conference
 
PDF
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf Conference
 
PPT
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf Conference
 
PPT
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf Conference
 
ODP
ZFConf 2010: Zend Framework and Doctrine
ZFConf Conference
 
PPT
ZFConf 2010: History of e-Shtab.ru
ZFConf Conference
 
PPTX
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf Conference
 
PPT
ZFConf 2010: Performance of Zend Framework Applications
ZFConf Conference
 
PPTX
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf Conference
 
PPT
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf Conference
 
PPT
ZFConf 2010: Using Message Queues in Day-to-Day Projects (Zend_Queue)
ZFConf Conference
 
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf Conference
 
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf Conference
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf Conference
 
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf Conference
 
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf Conference
 
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf Conference
 
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf Conference
 
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf Conference
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf Conference
 
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf Conference
 
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf Conference
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf Conference
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf Conference
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf Conference
 
ZFConf 2010: History of e-Shtab.ru
ZFConf Conference
 
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf Conference
 
ZFConf 2010: Performance of Zend Framework Applications
ZFConf Conference
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf Conference
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf Conference
 
ZFConf 2010: Using Message Queues in Day-to-Day Projects (Zend_Queue)
ZFConf Conference
 

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>