Your SlideShare is downloading. ×
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)

4,979
views

Published on


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

No Downloads
Views
Total Views
4,979
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
79
Comments
0
Likes
4
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

Transcript

  • 1. 27 марта 2010 г. Санкт-Петербург Dependency Injection (Внедрение Зависимостей) ZF, Zend_Application, DI Container, Symfony DI
  • 2. О Докладчике Кирилл Чебунин • Ведущий PHP разработчик Equelli, ltd. • Около 4 лет опыта PHP • Более 2х лет использования ZendFramework
  • 3. Выбор классов • Адаптеры • Плагины/Хелперы • Интерфейсы и Реализация
  • 4. Хранилище
  • 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
  • 12. Inversion Of Control (IOC)
  • 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>
  • 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. Инъекция через аннотации 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. Проблемы, советы, размышления Транзакции, сквозная функциональность
  • 20. Транзакции • Транзакции недоступны в сервисном слое в нашей реализации • Транзакции это уровень сервисов. • Может быть несколько источников данных.
  • 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. Использование нескольких менеджеров транзакций 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. Сквозная функциональность
  • 24. Аспектно-ориентированное программирование (АОП)
  • 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. Добавим Аннотаций 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. Хорошая архитектура — Простота конфигурации <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>