Your SlideShare is downloading. ×
0
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency Injection)
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
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

740

Published on

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

  • Be the first to like this

No Downloads
Views
Total Views
740
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • * Instead of your program running the system, the system runs your program * Controller
  • Transcript

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

    ×