0
ZF2 Modules and Services (And DI)Maurice KherlakianZend Technologies                        © All rights reserved. Zend Te...
Who am I?    • Zend Professional Services consultant    • Worked with PHP for about 10 years    • Based in Montreal     Li...
ZF2 Modules – What are they?    • Discrete blocks of code    • Allow for code re-use (not only within ZF2 but with other  ...
Why are they better than ZF1’s modules    • ZF1 modules had serious problems    • Tightly coupled with MVC    • Could not ...
Requirements for a module – Module class    • A namespaced class called Module          <?php          namespace Mymod;   ...
Requirements for a module – Directory    structure    • There is, of course, a recommended directory structure6   Zend Pro...
Requirements for a module - Registration    • In order for the application (Zend/Application) to run your module, it has  ...
Optional for a module – getConfig()    • Called automatically to get the module’s configuration and aggregate it      with...
Optional for a module – init()    • A module can have an init() method that fires upon initialization    • The ModuleManag...
Optional for a module – onBootstrap()     • And if init() is too early, ModuleManager automatically registers the       on...
Optional for a module – Dep solving     • Thru getProvides() and getDependencies()     • Off by default, can be turned on ...
ModuleManager     • It’s automatically instantiated in your ZendApplication     • It fulfills 3 functions:         Aggreg...
An MVC module     • In most cases that’s what you will want          <?php                                                ...
The missing link - bootstrapping – index.php          <?php                                                // /public/inde...
The missing link - bootstrapping – index.php     • Autoloading – it is the responsibility of index.php to set up autoloadi...
Modules distribution     • Any source you can think of         Pyrus         Git         Http         Tar & send      ...
Modules packaging     • Tar/Zip     • Phar (being careful that writes occur in location external to       the archive)17  ...
Location, location, location     DI - short summary     • Since the presentation was originally about ZendDi it’s only fai...
Location, location, location     DI - short summary         <?php //DI         class DbAdapter {            public functio...
Location, location, location     DI - short summary     • Consider the case that an Author needs a DbGateway, which needs ...
Location, location, location     DiC – ZendDiDi()          <?php          $config = array(               instance => array...
Location, location, location     DiC – ZendDiDi()     • The last line on the previous slide:                    $author = ...
Location, location, location     Location v/s Injection     • Service manager is a ServiceLocator !== DiC     • BUT DiC ==...
Location, location, location     ZendServiceManagerServiceManager()     • Service manager uses factories to generate its s...
Location, location, location     ZendServiceManagerServiceManager()          <?php          class ServiceConfiguration ext...
Location, location, location     ZendServiceManagerServiceManager()     • The example above purposely uses closures to ill...
Location, location, location     ZendServiceManagerServiceManager()     • The example above purposely uses closures to ill...
Location, location, location     Setting and retrieving the locator     • In most MVC components (e.g.Controllers) the Ser...
Location, location, location     Setting and retrieving the locator     • Controllers implement ServiceLocatorAwareInterfa...
Locating the injector or injecting the     locator?     • Although ServiceManager is now the goto dependency management   ...
Some references     • ZF2 module site: http://modules.zendframework.com/     • Rob Allen’s Skeleton:       https://github....
• Download ZF2 and happy coding!     http://zendframework.com/zf2                                                Thank You...
Upcoming SlideShare
Loading in...5
×

Zf2 phpquebec

2,773

Published on

ZF2 Modules and Service locators....

Published in: Technology, Art & Photos
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,773
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
62
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Zf2 phpquebec"

  1. 1. ZF2 Modules and Services (And DI)Maurice KherlakianZend Technologies © All rights reserved. Zend Technologies, Inc.
  2. 2. Who am I? • Zend Professional Services consultant • Worked with PHP for about 10 years • Based in Montreal Linkedin: http://ca.linkedin.com/in/mkherlakian Twitter: http://twitter.com/mkherlakian Email: maurice.k@zend.com2 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  3. 3. ZF2 Modules – What are they? • Discrete blocks of code • Allow for code re-use (not only within ZF2 but with other frameworks – Sf2 anyone?) • Physically a namespaced directory • If written well, distributable and re-usable • Examples:  User module (authentication – login/logout…)  ACL module  Blog module3 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  4. 4. Why are they better than ZF1’s modules • ZF1 modules had serious problems • Tightly coupled with MVC • Could not be easily reused • Bootstrapping expensive • Not self-contained • No dependency management ZF2 addresses all of these problems4 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  5. 5. Requirements for a module – Module class • A namespaced class called Module <?php namespace Mymod; class Module {} • That’s it!5 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  6. 6. Requirements for a module – Directory structure • There is, of course, a recommended directory structure6 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  7. 7. Requirements for a module - Registration • In order for the application (Zend/Application) to run your module, it has to be registered <?php //application.config.php return array( modules => array( //Which modules are we loading? Application, Mymod, ), module_listener_options => array( config_glob_paths => array( config/autoload/{,*.}{global,local}.php, ), config_cache_enabled => false, cache_dir => data/cache, module_paths => array( //What paths are we loading modules from? ./module, //We will look for a Module.php file in subdirs ./vendor, //one level down from this dir *by default* ), ), service_manager => array( //More on that later use_defaults => true, factories => array( ), ), );7 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  8. 8. Optional for a module – getConfig() • Called automatically to get the module’s configuration and aggregate it with the other modules • Best is to include a config file that returns a php array (best practice in ZF2 in general) <?php namespace Mymod; use ZendModuleManagerModuleManager, ZendMvcMvcEvent; class Module { public function getConfig() { return include(__DIR__./config/module.config.php); } }8 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  9. 9. Optional for a module – init() • A module can have an init() method that fires upon initialization • The ModuleManager is passed to the init function as an argument <?php namespace Mymod; use ZendModuleManagerModuleManager, ZendMvcMvcEvent; class Module { public function init(ModuleManager $e) { $e->events()->attach( loadModules.post, function($e) { echo postLoad from MyMod; }, 100); $e->events()->getSharedManager()->attach( __NAMESPACE__, dispatch, function($e) { echo "Only if dispatched to Mymod"; }, 100); } }9 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  10. 10. Optional for a module – onBootstrap() • And if init() is too early, ModuleManager automatically registers the onBootstrap method if found in the module • An MvcEvent is passed as the argument <?php namespace Mymod; use ZendModuleManagerModuleManager, ZendMvcMvcEvent; class Module { public function onBootstrap(MvcEvent $e) { $request = $e->getRequest(); } }10 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  11. 11. Optional for a module – Dep solving • Thru getProvides() and getDependencies() • Off by default, can be turned on <?php namespace Blog; class Module { public function getProvides() { return array( name => Blog, version => 0.1.0, ); } public function getDependencies() { return array( php => array( required => true, version => >=5.3.1, ), ext/mongo => array( required => true, version => >=1.2.0, ), ); } }11 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  12. 12. ModuleManager • It’s automatically instantiated in your ZendApplication • It fulfills 3 functions:  Aggregates enabled modules (allows you to iterate over them)  Aggregates the configuration from each module  Triggers the module initialization • There are many events for which the ModuleManager is passed as an argument • This allows you to provide listeners at practically any point in the code to get access to the manager12 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  13. 13. An MVC module • In most cases that’s what you will want <?php //module.config.php return array( router => array( routes => array( Mymod => array( type => ZendMvcRouterHttpLiteral, options => array( route => /mymod, defaults => array( controller => mymod, action => index, ), ), ), ), ), controller => array( classes => array( mymod => MymodControllerIndexController, ), ), view_manager => array( template_path_stack => array( __DIR__ . /../view, ), ), );13 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  14. 14. The missing link - bootstrapping – index.php <?php // /public/index.php require_once Loader/StandardAutoloader.php; use ZendLoaderStandardAutoloader, ZendServiceManagerServiceManager, ZendMvcServiceServiceManagerConfiguration; $loader = new StandardAutoloader(); $loader->registerNamespace(Application, module/Application/src/Application); $loader->registerNamespace(Mymod, module/Mymod/src/Application); spl_autoload_register(array($loader, autoload)); // Get application stack configuration chdir(dirname(__DIR__)); $configuration = include config/application.config.php; // Setup service manager $serviceManager = new ServiceManager(new ServiceManagerConfiguration($configuration[service_manager])); $serviceManager->setService(ApplicationConfiguration, $configuration); $serviceManager->get(ModuleManager)->loadModules(); // Run application $serviceManager->get(Application)->bootstrap()->run()->send();14 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  15. 15. The missing link - bootstrapping – index.php • Autoloading – it is the responsibility of index.php to set up autoloading • This is because modules have to be portable between different frameworks (reusability) • Any PSR-0 autoloader should work, it does not have to be ZF2’s autoloader  For example Rob Allen’s Skeleton module uses Composer’s autoloader • The next lines are the ServiceManager’s setup (more on it later)15 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  16. 16. Modules distribution • Any source you can think of  Pyrus  Git  Http  Tar & send  Composer • There is already a ZF2 modules site http://modules.zendframework.com/ (We need help! Want to contribute?)16 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  17. 17. Modules packaging • Tar/Zip • Phar (being careful that writes occur in location external to the archive)17 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  18. 18. Location, location, location DI - short summary • Since the presentation was originally about ZendDi it’s only fair that we talk about it! • DI is the practice of reducing coupling between classes by injecting dependent classes in the subject instead of instantiating them <?php //No DI class DbAdapter { public function __construct($host, $user, $pass, $db) { //... } } class Author { protected $_db; public function __construct($host, $user, $pass, $db) { $this->_db = new DbAdapter($host, $user, $pass, $db); } }18 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  19. 19. Location, location, location DI - short summary <?php //DI class DbAdapter { public function __construct($host, $user, $pass, $db) { //... } } class Author { protected $_db; public function __construct($db) { $this->_db = $db; } } $db = new DbAdapter(); $author = new Author($db); • That’s all it is – Really! Makes it easy to substitute the DB class for mocking, or to change it all together for instance, and promotes decoupling and reusability. The D in SOLID.19 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  20. 20. Location, location, location DI - short summary • Consider the case that an Author needs a DbGateway, which needs a DbAdapter, and a logging and caching class <?php $db = new DbAdapter(); $gateway = new DbGateway($db); $cache = new Cache(); $log = new Log(); $author = new Author($db, $gateway, $cache, $log); $authors = $author->fetchAll(); • 5 lines of code for initialization, but only one line for what we really need to do. Lots of boilerplate code • Enter Dependency Injection Containers, or DiC – ZendDi is one of them, so is the Symfony DiC, and a number of others20 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  21. 21. Location, location, location DiC – ZendDiDi() <?php $config = array( instance => array( Author => array( parameters => array( gateway => DbGateway, cache => Cache, log => Log ) ), DbGateway => array( parameters => array( db => DbAdapter, ) ), DbAdapter => array( parameters => array( host => somehost, user => someuser, pass => somepass, db => ‘somedb ) ), Cache => array( ), Log => array( ) ) ); $di = new ZendDiDi(); $di->configure(new ZendDiConfiguration($config)); $author = $di->get(Author);21 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  22. 22. Location, location, location DiC – ZendDiDi() • The last line on the previous slide: $author = $di->get(Author); Returns a fully configured Author object, following the definition we provided • DiC does instantiation and auto-wiring • ZendDi, although difficult to show here, is a complex solution for complex problems – it can easily be abused • For simpler problems, and more in line with the PHP philosophy, ServiceManager replaced it22 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  23. 23. Location, location, location Location v/s Injection • Service manager is a ServiceLocator !== DiC • BUT DiC === Service Locator • One main difference is that the subject requiring the dependencies is:  Not aware of the DiC when using DI (the dependency is injected)  Is aware of the locator in the case of SL, and asks the locator to obtain the dependency • ServiceManager is a service locator Think back to index.php: $serviceManager->get(ModuleManager)->loadModules(); • Martin Fowler is the subject matter expert on this: http://martinfowler.com/articles/injection.html23 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  24. 24. Location, location, location ZendServiceManagerServiceManager() • Service manager uses factories to generate its services • Factory can be a class implementing ZendServiceManagerFactoryInterface or a php closure24 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  25. 25. Location, location, location ZendServiceManagerServiceManager() <?php class ServiceConfiguration extends Configuration { public function configureServiceManager(ServiceManager $serviceManager) { $serviceManager->setFactory(author, function(ServiceManager $sm) { $dbGateway = $sm->get(db_gateway); $cache = $sm->get(cache); $log = $sm->get(log); return new Author($dbGateway, $cache, $log); } ); $serviceManager->setShared(author, false); $serviceManager->setFactory(db_gateway, function(ServiceManager $sm){ $dbAdapter = $sm->get(db_adapter); return new DbGateway($dbAdapter); } ); $serviceManager->setFactory(db_adapter, function(ServiceManager $sm) { //Using hard-coded values for the example, but normally you would either create a factory //and inject the values from a config file //or get the configuration from the ServiceManager and read the valuees in return new DbAdapter(somehost, someuser, somepass, somedb); } ); $serviceManager->setFactory(cache, function(ServiceManager $sm) { return new Cache(); } ); $serviceManager->setFactory(log, function(ServiceManager $sm) { return new Log(); } ); } } $config = new ServiceConfiguration(); $sm = new ServiceManager(); $config->configureServiceManager($sm); $author = $sm->get(author);25 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  26. 26. Location, location, location ZendServiceManagerServiceManager() • The example above purposely uses closures to illustrate that a full-fledged factory is not needed • But in a lot of cases, implementing a factory makes sense - rewriting DbAdapter from the above example as a factory: <?php use ZendServiceManagerFactoryInterface; //The factory class class AuthorFactory implements FactoryInterface { public function createService(ZendServiceManagerServiceLocatorInterface $sl) { $dbGateway = $sl->get(db_gateway); $cache = $sl->get(cache); $log = $sl->get(log); return new Author($dbGateway, $cache, $log); } } //And the configuration class class ServiceConfiguration extends Configuration { public function configureServiceManager(ServiceManager $serviceManager) { //... $serviceManager->setFactory(author, AuthorFactory); //... } }26 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  27. 27. Location, location, location ZendServiceManagerServiceManager() • The example above purposely uses closures to illustrate that a full-fledged factory is not needed • But in a lot of cases, implementing a factory makes sense - rewriting DbAdapter form the above example as a factory: <?php use ZendServiceManagerFactoryInterface; //The factory class class AuthorFactory implements FactoryInterface { public function createService(ZendServiceManagerServiceLocatorInterface $sl) { $dbGateway = $sl->get(db_gateway); $cache = $sl->get(cache); $log = $sl->get(log); return new Author($dbGateway, $cache, $log); } } //And the configuration class class ServiceConfiguration extends Configuration { public function configureServiceManager(ServiceManager $serviceManager) { //... $serviceManager->setFactory(author, AuthorFactory); //... } }27 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  28. 28. Location, location, location Setting and retrieving the locator • In most MVC components (e.g.Controllers) the ServiceManager component is composed automatically by the MVC stack • The interface ZendServiceManagerServiceLocatorAwareInterface can be implemented to ensure that a service locator is composed in the subject class • Two methods, SetServiceLocator(ServiceLocatorInterface $locator) and getServiceLocator() must be implemented • Notice that the Component is ServiceManager(), but the interface is ServiceLocatorInterface. This is to allow you to provide an alternative implementation of service locator.28 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  29. 29. Location, location, location Setting and retrieving the locator • Controllers implement ServiceLocatorAwareInterface therefore <?php namespace MymodController; use ZendMvcControllerActionController, ZendViewModelViewModel; class IndexController extends ActionController { public function indexAction() { $sl = $this->getServiceLocator(); $sl->get(author); return new ViewModel(); } }29 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  30. 30. Locating the injector or injecting the locator? • Although ServiceManager is now the goto dependency management component in ZF2, Di actually still exists as a fallback (by default) • One can specify a collection AbstractFactories to ServiceManager on which it will fall back if it does not find the target class • Therefore, ZendServiceManagerDiDiAbstractFactory is an abstract factory to which the name of the object is passed if it is not found by ServiceManager (the order can be changed) • You can also, of course, provide your own service factory (Proxy class to other frameworks maybe?)30 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  31. 31. Some references • ZF2 module site: http://modules.zendframework.com/ • Rob Allen’s Skeleton: https://github.com/zendframework/ZendSkeletonApplication • Matthew’s discussion on Modules: http://mwop.net/blog/267-Getting- started-writing-ZF2-modules.html • Ralph on the decisions that drove to ServiceManager: http://zend- framework-community.634137.n4.nabble.com/Services-Instances- Dependencies-in-ZF2-td4584632.html • SOLID OO design: http://en.wikipedia.org/wiki/SOLID_(object- oriented_design)31 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  32. 32. • Download ZF2 and happy coding! http://zendframework.com/zf2 Thank You! http://twitter.com/mkherlakian32 Zend Professional Services © All rights reserved. Zend Technologies, Inc.
  1. A particular slide catching your eye?

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

×