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)

on

  • 5,583 views

 

Statistics

Views

Total Views
5,583
Views on SlideShare
2,656
Embed Views
2,927

Actions

Likes
4
Downloads
79
Comments
0

6 Embeds 2,927

http://www.zfconf.ru 2755
http://zendframework.ru 148
http://www.slideshare.net 21
http://static.slidesharecdn.com 1
http://unic.ru 1
http://translate.googleusercontent.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • 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>
  • //[..................] /** * 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(); } } //[.....] }
  • Сквозная функциональность
  • Аспектно-ориентированное программирование (АОП)
  • Динамические прокси 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>