27 марта 2010 г.
                                     Санкт-Петербург




   Dependency Injection
(Внедрение Зависимостей)...
О Докладчике

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

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

[production]
resources.log.file.writerName = "Stream"
resources.log.file.writerParams.stream = "/var/log...
Zend_Application
      & Dependency Injection
           class My_Application_Resource_Service_UserService
              e...
Zend_Application
      & Dependency Injection
           class Zend_Application_Resource_Log
              extends Zend_Ap...
Конфигурация вместо кода

<service id="log" class="Zend_Log" constructor="factory">
     <argument type="collection">
    ...
Dependency Injection —
      A specific form of Inversion of Control (IOC)



Внедрение зависимости —
     Специфическая ф...
Inversion Of Control (IOC)
PHP DI Containers

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

•   Поддержка XML, YAML, PHP и INI конфигураций
•   Ленивая загрузка
•   Constructor and Method Inje...
Замена контейнера

require_once 'Zend/Application.php';
require_once 'sfServiceContainerBuilder.php';
require_once 'sfServ...
Dependencies.xml
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony-project.org/2.0/container">

    ...
//[..................]
/**
  * Inject properties on Pre-Dispatch
  */
public function preDispatch()
{
        $actionContr...
Инъекция через аннотации
class UserController extends Zend_Controller_Action
{
   /**
    * Logger
    * @var Zend_Log
   ...
Проблемы, советы, размышления


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


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

interface TransactionManager
{
   /**
    * Start a new transaction
    * @return unknown_type...
Использование нескольких
                 менеджеров транзакций
class MultipleTransactionManager implements TransactionMan...
Сквозная функциональность
Аспектно-ориентированное
 программирование (АОП)
Динамические прокси

class SomeClass
{
   public function someMethod() {}
}

class __GeneratedDynamicProxy__ extends SomeC...
Добавим Аннотаций

public function someMethod()                           /**
{                                           ...
Хорошая архитектура —
        Простота конфигурации
<service id="actionHelperStack"
     class="Zend_Controller_Action_Hel...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
Upcoming SlideShare
Loading in...5
×

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

5,084

Published on

0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,084
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
80
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

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

  1. 1. 27 марта 2010 г. Санкт-Петербург Dependency Injection (Внедрение Зависимостей) ZF, Zend_Application, DI Container, Symfony DI
  2. 2. О Докладчике Кирилл Чебунин • Ведущий PHP разработчик Equelli, ltd. • Около 4 лет опыта PHP • Более 2х лет использования ZendFramework
  3. 3. Выбор классов • Адаптеры • Плагины/Хелперы • Интерфейсы и Реализация
  4. 4. Хранилище
  5. 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. 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. 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. 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. 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. 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. 11. Dependency Injection — A specific form of Inversion of Control (IOC) Внедрение зависимости — Специфическая форма «обращения контроля» Взято из ®Wikipedia, the free encyclopedia
  12. 12. Inversion Of Control (IOC)
  13. 13. PHP DI Containers • Symfony Dependency Injection • Yadif_Container • Seasar DI Container (S2Container) • Phemto • Xyster_Container • TYPO3 • ...........
  14. 14. Symfony DI Container • Поддержка XML, YAML, PHP и INI конфигураций • Ленивая загрузка • Constructor and Method Injection • Shared/NotShared ресурсы • Конфигураторы • Алиасы
  15. 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. 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>
  17. 17. //[..................] /** * 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 ); } } } }
  18. 18. Инъекция через аннотации 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); } }
  19. 19. Проблемы, советы, размышления Транзакции, сквозная функциональность
  20. 20. Транзакции • Транзакции недоступны в сервисном слое в нашей реализации • Транзакции это уровень сервисов. • Может быть несколько источников данных.
  21. 21. Общий интерфейс транзакций 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(); }
  22. 22. Использование нескольких менеджеров транзакций 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(); } } //[.....] }
  23. 23. Сквозная функциональность
  24. 24. Аспектно-ориентированное программирование (АОП)
  25. 25. Динамические прокси 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__ )); } }
  26. 26. Добавим Аннотаций 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'); }
  27. 27. Хорошая архитектура — Простота конфигурации <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>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×