News Archive
PhpRiot Newsletter
Your Email Address:

More information

Create your own framework... on top of the Symfony2 Components (part 9)

Note: This article was originally published at Planet PHP on 19 January 2012.
Planet PHP

Our framework is still missing a major characteristic of any good framework: extensibility. Being extensible means that the developer should be able to easily hook into the framework life cycle to modify the way the request is handled.

What kind of hooks are we talking about? Authentication or caching for instance. To be flexible, hooks must be plug-and-play; the ones you "register" for an application are different from the next one depending on your specific needs. Many software have a similar concept like Drupal or Wordpress. In some languages, there is even a standard like WSGI in Python or Rack in Ruby.

As there is no standard for PHP, we are going to use a well-known design pattern, the Observer, to allow any kind of behaviors to be attached to our framework; the Symfony2 EventDispatcher Component implements a lightweight version of this pattern:

{ "require": { "symfony/class-loader": "2.1.*", "symfony/http-foundation": "2.1.*", "symfony/routing": "2.1.*", "symfony/http-kernel": "2.1.*", "symfony/event-dispatcher": "2.1.*" }, "autoload": { "psr-0": { "Simplex": "src/", "Calendar": "src/" } } } A

How does it work? The dispatcher, the central object of the event dispatcher system, notifies listeners of an event dispatched to it. Put another way: your code dispatches an event to the dispatcher, the dispatcher notifies all registered listeners for the event, and each listener do whatever it wants with the event.

As an example, let's create a listener that transparently adds the Google Analytics code to all responses.

To make it work, the framework must dispatch an event just before returning the Response instance:

A // A namespace Simplex; A use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; A class Framework implements HttpKernelInterface { protected $matcher; protected $resolver; protected $dispatcher; A public function __construct(EventDispatcher $dispatcher, UrlMatcherInterface $matcher, ControllerResolverInterface $resolver) { $this-matcher = $matcher; $this-resolver = $resolver; $this-dispatcher = $dispatcher; } A public function handle(Request $request) { try { $request-attributes-add($this-matcher-match($request-getPathInfo()

Truncated by Planet PHP, read more at the original (another 22466 bytes)