zend framework 2.0 patterns
DESCRIPTION
Describes problems encountered in Zend Framework 1.X, and approaches being uTRANSCRIPT
![Page 1: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/1.jpg)
© All rights reserved. Zend Technologies, Inc.
Zend Framework 2 PatternsMatthew Weier O'PhinneyProject Lead, Zend Framework
![Page 2: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/2.jpg)
© All rights reserved. Zend Technologies, Inc.
● Namespaces and Autoloading● Exceptions● Configuration● Plugin systems● Dispatching● Inversion of Control
Roadmap for today
![Page 3: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/3.jpg)
© All rights reserved. Zend Technologies, Inc.
Format● List The Problems● Detail the ZF2 Approach
![Page 4: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/4.jpg)
© All rights reserved. Zend Technologies, Inc.
But first, some history
![Page 5: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/5.jpg)
© All rights reserved. Zend Technologies, Inc.
Zend Framework 1.X● 1.0 Released in July 2007● Largely evolutionary development
▶ Inconsistencies in APIs, particularly surrounding plugins and configuration
▶ Best practices have been discovered over time▶ Many key features for modern applications have
been added in recent versions
![Page 6: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/6.jpg)
© All rights reserved. Zend Technologies, Inc.
Zend Framework 2.0● First new major release
▶ Allowing us to break backwards compatibility● Focus is on:
▶ Consistency▶ Performance▶ Documentation▶ User productivity
![Page 7: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/7.jpg)
7 © All rights reserved. Zend Technologies, Inc.
Namespaces and Autoloading
![Page 8: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/8.jpg)
© All rights reserved. Zend Technologies, Inc.
The Problems● Lengthy class names
▶ Difficult to refactor▶ Difficult to retain semantics with shorter names
● Performance issues▶ Many classes are used JIT, and shouldn't be
loaded until needed● Missing require_once statements lead to errors
![Page 9: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/9.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach: Namespaces● Formalize the prefixes used in ZF1
▶ Namespace separator correlates to directory separator
● Help identify dependencies (imports)▶ Allows refactoring using different
implementations easier▶ Makes packaging easier
![Page 10: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/10.jpg)
© All rights reserved. Zend Technologies, Inc.
Namespaces
namespace Zend\EventManager;
use Zend\Stdlib\CallbackHandler;
class EventManager implements EventCollection{ /* ... */}
namespace Zend\EventManager;
use Zend\Stdlib\CallbackHandler;
class EventManager implements EventCollection{ /* ... */}
![Page 11: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/11.jpg)
© All rights reserved. Zend Technologies, Inc.
Namespaces● Interfaces as namespaces
▶ Interface names are adjectives or nouns▶ Concrete implementations in a sub-namespace
named after the interface▶ Contract-Oriented paradigm
![Page 12: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/12.jpg)
© All rights reserved. Zend Technologies, Inc.
Interfaces as NamespacesZend/Session|-- Storage.php`-- Storage |-- ArrayStorage.php `-- SessionStorage.php
namespace Zend\Session;
interface Storage { /* ... */}
namespace Zend\Session;
interface Storage { /* ... */}
namespace Zend\Session\Storage;use ArrayObject, Zend\Session\Storage, Zend\Session\Exception;class ArrayStorage extends ArrayObject implements Storage{ /* ... */ }
namespace Zend\Session\Storage;use ArrayObject, Zend\Session\Storage, Zend\Session\Exception;class ArrayStorage extends ArrayObject implements Storage{ /* ... */ }
![Page 13: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/13.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach: Autoloading● No more require_once calls!● Multiple approaches
▶ ZF1-style include_path autoloader▶ Per-namespace/prefix autoloading▶ Class-map autoloading
![Page 14: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/14.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF1-Style Autoloading
require_once 'Zend/Loader/StandardAutoloader.php';$loader = new Zend\Loader\StandardAutoloader(array( 'fallback_autoloader' => true,));$loader->register();
require_once 'Zend/Loader/StandardAutoloader.php';$loader = new Zend\Loader\StandardAutoloader(array( 'fallback_autoloader' => true,));$loader->register();
![Page 15: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/15.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 NS/Prefix Autoloading
require_once 'Zend/Loader/StandardAutoloader.php';$loader = new Zend\Loader\StandardAutoloader();$loader->registerNamespace( 'My', __DIR__ . '/../library/My') ->registerPrefix( 'Phly_', __DIR__ . '/../library/Phly');$loader->register();
require_once 'Zend/Loader/StandardAutoloader.php';$loader = new Zend\Loader\StandardAutoloader();$loader->registerNamespace( 'My', __DIR__ . '/../library/My') ->registerPrefix( 'Phly_', __DIR__ . '/../library/Phly');$loader->register();
![Page 16: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/16.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Class-Map Autoloading
return array( 'My\Foo\Bar' => __DIR__ . '/Foo/Bar.php',);
return array( 'My\Foo\Bar' => __DIR__ . '/Foo/Bar.php',);
require_once 'Zend/Loader/ClassMapAutoloader.php';$loader = new Zend\Loader\ClassMapAutoloader();$loader->registerAutoloadMap( __DIR__ . '/../library/.classmap.php');$loader->register();
require_once 'Zend/Loader/ClassMapAutoloader.php';$loader = new Zend\Loader\ClassMapAutoloader();$loader->registerAutoloadMap( __DIR__ . '/../library/.classmap.php');$loader->register();
![Page 17: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/17.jpg)
17 © All rights reserved. Zend Technologies, Inc.
Exceptions
![Page 18: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/18.jpg)
© All rights reserved. Zend Technologies, Inc.
The Problems● All exceptions derived from a common class● No ability to extend more semantic exception
types offered in SPL
![Page 19: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/19.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach● Eliminated Zend_Exception● Each component defines a marker Exception
interface● Additional exception types are created in an
Exception subnamespace▶ These extend SPL exceptions, and implement
the component-level exception interface
![Page 20: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/20.jpg)
© All rights reserved. Zend Technologies, Inc.
What the solution provides● Catch specific exception types● Catch SPL exception types● Catch any component-level exception● Catch based on global exception type
![Page 21: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/21.jpg)
© All rights reserved. Zend Technologies, Inc.
Exceptions in useZend/EventManager|-- Exception.php`-- Exception `-- InvalidArgument- Exception.php
Zend/EventManager|-- Exception.php`-- Exception `-- InvalidArgument- Exception.php
namespace Zend\EventManager;
interface Exception {}
namespace Zend\EventManager;
interface Exception {}
namespace Zend\EventManager\Exception;
use Zend\EventManager\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements Exception{}
namespace Zend\EventManager\Exception;
use Zend\EventManager\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements Exception{}
![Page 22: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/22.jpg)
© All rights reserved. Zend Technologies, Inc.
Exceptions in use
namespace Zend\EventManager\Exception;use Zend\EventManager\Exception;try { $events->trigger('foo.bar', $object);} catch (InvalidArgumentException $e) {} catch (Exception $e) {} catch (\InvalidArgumentException $e) {} catch (\Exception $e) {}
namespace Zend\EventManager\Exception;use Zend\EventManager\Exception;try { $events->trigger('foo.bar', $object);} catch (InvalidArgumentException $e) {} catch (Exception $e) {} catch (\InvalidArgumentException $e) {} catch (\Exception $e) {}
![Page 23: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/23.jpg)
23 © All rights reserved. Zend Technologies, Inc.
Configuration
![Page 24: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/24.jpg)
© All rights reserved. Zend Technologies, Inc.
The Problems● Case-SeNSItiviTy● Varying APIs
▶ setOptions()▶ setConfig()▶ __construct()
▶ explicit setters
![Page 25: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/25.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach● Option names will be
lowercase_underscore_separated_words
● Standard solution across components▶ setOptions() style, proxying to setters, or▶ per-component configuration objects
![Page 26: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/26.jpg)
© All rights reserved. Zend Technologies, Inc.
setOptions() styleclass Foo{ public function setOptions($options) { if (!is_array($options) && !($options instanceof \Traversable) ) { throw new \InvalidArgumentException(); }
foreach ($options as $key => $value) { $method = normalize($key); if (method_exists($this, $method)) { $this->$method($value); } } }}
class Foo{ public function setOptions($options) { if (!is_array($options) && !($options instanceof \Traversable) ) { throw new \InvalidArgumentException(); }
foreach ($options as $key => $value) { $method = normalize($key); if (method_exists($this, $method)) { $this->$method($value); } } }}
![Page 27: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/27.jpg)
© All rights reserved. Zend Technologies, Inc.
Options object styleclass FooOptions extends Options{ public $bar; public $baz;
public function __construct($options = null) { if (!is_array($options) && !($options instanceof \Traversable) ) { throw new \InvalidArgumentException(); }
foreach ($options as $key => $value) { $prop = normalize($key); $this->$prop = $value; } }}
class FooOptions extends Options{ public $bar; public $baz;
public function __construct($options = null) { if (!is_array($options) && !($options instanceof \Traversable) ) { throw new \InvalidArgumentException(); }
foreach ($options as $key => $value) { $prop = normalize($key); $this->$prop = $value; } }}
![Page 28: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/28.jpg)
© All rights reserved. Zend Technologies, Inc.
Options object style
class Foo{ public function __construct(Options $options = null) { if (null !== $options) { foreach ($options as $key => $value) { $this->$key = $value; } } }}
class Foo{ public function __construct(Options $options = null) { if (null !== $options) { foreach ($options as $key => $value) { $this->$key = $value; } } }}
![Page 29: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/29.jpg)
29 © All rights reserved. Zend Technologies, Inc.
Plugin Architectures
![Page 30: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/30.jpg)
© All rights reserved. Zend Technologies, Inc.
Terminology● For our purposes, a “plugin” is any class that
is determined at runtime.▶ Action and view helpers▶ Adapters▶ Filters and validators
![Page 31: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/31.jpg)
© All rights reserved. Zend Technologies, Inc.
The Problems● Varying approaches to dynamically discovering
plugin classes▶ Prefix-path stacks (most common)▶ Paths relative to the calling class▶ Setters to indicate classes
● Most common approach is terrible▶ Bad performance▶ Hard to debug▶ No caching of discovered plugins
![Page 32: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/32.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach: Plugin Broker● Separate Plugin Location interface
▶ Allows varying implementation of plugin lookup● Separate Plugin Broker interface
▶ Composes a Plugin Locator
![Page 33: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/33.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach: Plugin Broker● Standard implementation across components
▶ Subclassing standard implementation allows type-hinting, caching discovered plugins, etc.
▶ while allowing you to substitute your own implementations
● Class-map location by default● 2-5x performance gains!● Easier to debug
![Page 34: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/34.jpg)
© All rights reserved. Zend Technologies, Inc.
Plugin class locationnamespace Zend\Loader;
interface ShortNameLocater{ public function isLoaded($name); public function getClassName($name); public function load($name);}
namespace Zend\Loader;
interface ShortNameLocater{ public function isLoaded($name); public function getClassName($name); public function load($name);}
namespace Zend\View;use Zend\Loader\PluginClassLoader;class HelperLoader extends PluginClassLoader{ protected $plugins = array( 'action' => 'Zend\View\Helper\Action', 'baseurl' => 'Zend\View\Helper\BaseUrl', /* ... */ );}
namespace Zend\View;use Zend\Loader\PluginClassLoader;class HelperLoader extends PluginClassLoader{ protected $plugins = array( 'action' => 'Zend\View\Helper\Action', 'baseurl' => 'Zend\View\Helper\BaseUrl', /* ... */ );}
![Page 35: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/35.jpg)
© All rights reserved. Zend Technologies, Inc.
Plugin broker
namespace Zend\Loader;
interface Broker{ public function load($plugin, array $options = null); public function getPlugins(); public function isLoaded($name); public function register($name, $plugin); public function unregister($name); public function setClassLoader( ShortNameLocater $loader); public function getClassLoader();}
namespace Zend\Loader;
interface Broker{ public function load($plugin, array $options = null); public function getPlugins(); public function isLoaded($name); public function register($name, $plugin); public function unregister($name); public function setClassLoader( ShortNameLocater $loader); public function getClassLoader();}
![Page 36: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/36.jpg)
© All rights reserved. Zend Technologies, Inc.
Plugin brokerclass HelperBroker extends PluginBroker { protected $defaultClassLoader = 'Zend\View\HelperLoader'; protected $view; public function setView(Renderer $view) {} public function getView() {} public function load($plugin, array $options = null) { $helper = parent::load($plugin, $options); if (null !== ($view = $this->getView())) { $helper->setView($view); } return $helper; } protected function validatePlugin($plugin) { if (!$plugin instanceof Helper) { throw new InvalidHelperException(); } return true; }}
class HelperBroker extends PluginBroker { protected $defaultClassLoader = 'Zend\View\HelperLoader'; protected $view; public function setView(Renderer $view) {} public function getView() {} public function load($plugin, array $options = null) { $helper = parent::load($plugin, $options); if (null !== ($view = $this->getView())) { $helper->setView($view); } return $helper; } protected function validatePlugin($plugin) { if (!$plugin instanceof Helper) { throw new InvalidHelperException(); } return true; }}
![Page 37: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/37.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach: Events● Trigger events at interesting points in your
application▶ Use as basic subject/observer pattern▶ Or as intercepting filters▶ Or a full-fledged Aspect-Oriented Programming
system
![Page 38: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/38.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach: Events● Compose an EventManager to a class● Attach handlers to events
▶ Handlers receive an Event● event name ● target (calling) object● parameters passed
▶ Handlers can also be attached statically
![Page 39: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/39.jpg)
© All rights reserved. Zend Technologies, Inc.
Triggering an event
public function doSomething( $with, $params = array()) { $this->events()->trigger( __FUNCTION__, compact('with', 'params') ); /* ... */}
public function doSomething( $with, $params = array()) { $this->events()->trigger( __FUNCTION__, compact('with', 'params') ); /* ... */}
![Page 40: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/40.jpg)
© All rights reserved. Zend Technologies, Inc.
Listening to an event
use Zend\EventManager\EventManager as Events;
$events = new Events();$events->attach('doSomething', function($e) use ($log) { $event = $e->getName(); $target = get_class($e->getTarget()); $params = json_encode($e->getParams()); $message = sprintf('%s (%s): %s', $event, $target, $params); $log->info($message);});
use Zend\EventManager\EventManager as Events;
$events = new Events();$events->attach('doSomething', function($e) use ($log) { $event = $e->getName(); $target = get_class($e->getTarget()); $params = json_encode($e->getParams()); $message = sprintf('%s (%s): %s', $event, $target, $params); $log->info($message);});
![Page 41: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/41.jpg)
© All rights reserved. Zend Technologies, Inc.
Attaching statically to an event
use Zend\EventManager\StaticEventManager as AllEvents;
$events = AllEvents::getInstance();
// Specify the class composing an EventManager // as first arg$events->attach('Foo', 'doSomething', function($e) {});
use Zend\EventManager\StaticEventManager as AllEvents;
$events = AllEvents::getInstance();
// Specify the class composing an EventManager // as first arg$events->attach('Foo', 'doSomething', function($e) {});
![Page 42: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/42.jpg)
42 © All rights reserved. Zend Technologies, Inc.
Dispatchers
![Page 43: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/43.jpg)
© All rights reserved. Zend Technologies, Inc.
The Problems● Not terribly performant● Hard to customize● Hard to inject controllers with dependencies● Forces pre-initialization of resources if you
want them configured by Zend_Application
![Page 44: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/44.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach● Discrete Request, Response, and Dispatchable
interfaces▶ Request encompasses request environment▶ Response aggregates response returned▶ Dispatchable objects formalize a Strategy
pattern
![Page 45: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/45.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach● Anything Dispatchable can be attached to the
MVC▶ Server components (XML-RPC, JSON-RPC, etc.)
● Allows building your own MVC approach▶ Do you want action methods to receive explicit
arguments?▶ Do you want to select a different action method
based on request headers?
![Page 46: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/46.jpg)
© All rights reserved. Zend Technologies, Inc.
MVC Interfacesinterface Message{ public function setMetadata($spec, $value = null); public function getMetadata($key = null); public function setContent($content); public function getContent();}
interface Message{ public function setMetadata($spec, $value = null); public function getMetadata($key = null); public function setContent($content); public function getContent();}
interface Request extends Message{ public function __toString(); public function fromString($string);}
interface Request extends Message{ public function __toString(); public function fromString($string);}
interface Response extends Message{ public function __toString(); public function fromString($string); public function send();}
interface Response extends Message{ public function __toString(); public function fromString($string); public function send();}
![Page 47: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/47.jpg)
© All rights reserved. Zend Technologies, Inc.
MVC Interfaces
interface Dispatchable{ public function dispatch( Request $request, Response $response = null);}
interface Dispatchable{ public function dispatch( Request $request, Response $response = null);}
![Page 48: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/48.jpg)
48 © All rights reserved. Zend Technologies, Inc.
Inversion of Control
![Page 49: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/49.jpg)
© All rights reserved. Zend Technologies, Inc.
The Problems● How do objects get dependencies?
▶ In particular, how do Controllers get dependencies?
![Page 50: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/50.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach● Service Locator
▶ Basic pattern: ● set($name, $service)● get($name)
▶ Formalization of application services(mailer, logger, profiler, etc.)
▶ Good interface for typehinting
![Page 51: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/51.jpg)
© All rights reserved. Zend Technologies, Inc.
Service Locator
use Zend\Di\ServiceLocator, Zend\EventManager\EventManager;
class MyLocator extends ServiceLocator{ protected $events; protected $map = array('events' => 'getEvents');
public function getEvents() { if (null !== $this->events) { return $this->events; } $this->events = new EventManager(); return $this->events; }}
use Zend\Di\ServiceLocator, Zend\EventManager\EventManager;
class MyLocator extends ServiceLocator{ protected $events; protected $map = array('events' => 'getEvents');
public function getEvents() { if (null !== $this->events) { return $this->events; } $this->events = new EventManager(); return $this->events; }}
![Page 52: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/52.jpg)
© All rights reserved. Zend Technologies, Inc.
ZF2 Approach● Dependency Injection Container
▶ Scaffolding for constructor and setter injection▶ Use programmatically, or from configuration▶ Typically used to seed a service locator
![Page 53: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/53.jpg)
© All rights reserved. Zend Technologies, Inc.
Dependency Injection
$db = new Definition('My\Db\Adapter\Sqlite');$db->setParam('name', __DIR__ . '/../data/db/users.db');
$mapper = new Definition('My\Mapper\Db');$mapper->addMethodCall( 'setAdapter', array(new Reference('db')));
$service = new Definition('My\Resource\Users');$service->setParam('mapper', new Reference('mapper'));
$di = new DependencyInjector;$di->setDefinitions(array( 'db' => $db, 'mapper' => $mapper, 'users' => $service,));
$users = $di->get('users'); // My\Resource\Users
$db = new Definition('My\Db\Adapter\Sqlite');$db->setParam('name', __DIR__ . '/../data/db/users.db');
$mapper = new Definition('My\Mapper\Db');$mapper->addMethodCall( 'setAdapter', array(new Reference('db')));
$service = new Definition('My\Resource\Users');$service->setParam('mapper', new Reference('mapper'));
$di = new DependencyInjector;$di->setDefinitions(array( 'db' => $db, 'mapper' => $mapper, 'users' => $service,));
$users = $di->get('users'); // My\Resource\Users
![Page 54: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/54.jpg)
© All rights reserved. Zend Technologies, Inc.
Controllers as services● Solves issue of controller dependencies● Each request only instantiates what's needed
for that request● Better testability of controllers
![Page 55: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/55.jpg)
© All rights reserved. Zend Technologies, Inc.
Controllers as services
$userController = new Definition('Site\Controller\User');$userController->setParam( 'service', new Reference('users'));$di->setDefinition($userController, 'controller-user');
// Inside dispatcher:$controller = $di->get($controllerName);$result = $controller->dispatch($request, $response);
$userController = new Definition('Site\Controller\User');$userController->setParam( 'service', new Reference('users'));$di->setDefinition($userController, 'controller-user');
// Inside dispatcher:$controller = $di->get($controllerName);$result = $controller->dispatch($request, $response);
![Page 56: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/56.jpg)
56 © All rights reserved. Zend Technologies, Inc.
More to come!
![Page 57: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/57.jpg)
© All rights reserved. Zend Technologies, Inc.
Zend Framework 2.0● Schedule:
▶ MVC milestone by end of May▶ Preview Release following MVC milestone▶ Beta release during summer▶ Stable by end-of-year
![Page 58: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/58.jpg)
58 © All rights reserved. Zend Technologies, Inc.
Resources
![Page 59: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/59.jpg)
© All rights reserved. Zend Technologies, Inc.
● ZF2 Wiki: http://bit.ly/zf2wiki● ZF2 Git information: http://bit.ly/zf2gitguide● ZF2 MVC sandbox:
git://git.mwop.net/zf2sandbox.git● ZF2 DI prototype: http://bit.ly/gBBnDS
![Page 60: Zend Framework 2.0 Patterns](https://reader035.vdocuments.us/reader035/viewer/2022062303/554c0f3db4c905ec518b4776/html5/thumbnails/60.jpg)
60 © All rights reserved. Zend Technologies, Inc.
Thank you!● http://framework.zend.com/● http://twitter.com/weierophinney