Commit d61569b6 authored by Fabien Potencier's avatar Fabien Potencier

merged branch igorw/lazy-dispatcher (PR #705)

This PR was submitted for the 1.0 branch but it was merged into the master branch instead (closes #705).

Discussion
----------

Make dispatcher lazy, do not trigger its creation on middleware definition

The dispatcher has quite a few dependencies due to all of the subscribers
that are added to it. One of these is the logger, several other services
are affected as well though.

The listener shortcut methods like on(), before(), after(), error() all
force creation of the dispatcher and thus all of its dependencies. This
makes it impossible to have lazy configuration of those services.

The specific issue that triggered this was lazy configuration of the logger,
which simply does not work once you have before() or after().

By using extend(), all of those shortcut calls can delay the creation of
the dispatcher and thus solve the issue. It will add a slight overhead, but
it should be relatively small, since the results of creating a service are
memoized through share().

Commits
-------

efa0383 Add changelog entry for lazy dispatcher proxies
59b56b0 Make dispatcher lazy, do not trigger its creation on middleware definition
parents e9e1b209 41fc16a6
......@@ -4,6 +4,8 @@ Changelog
1.1.0 (2013-XX-XX)
------------------
* Make dispatcher proxy methods ``on``, ``before``, ``after`` and ``error``
lazy, so that they will not instantiate the dispatcher early.
* **2013-05-03: Dropped support for 2.1 and 2.2 versions of symfony.
1.0.0 (2013-05-03)
......
......@@ -258,7 +258,11 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
*/
public function on($eventName, $callback, $priority = 0)
{
$this['dispatcher']->addListener($eventName, $callback, $priority);
$this['dispatcher'] = $this->share($this->extend('dispatcher', function ($dispatcher, $app) use ($callback, $priority, $eventName) {
$dispatcher->addListener($eventName, $callback, $priority);
return $dispatcher;
}));
}
/**
......@@ -272,7 +276,7 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
*/
public function before($callback, $priority = 0)
{
$this['dispatcher']->addListener(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($callback) {
$this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
......@@ -296,7 +300,7 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
*/
public function after($callback, $priority = 0)
{
$this['dispatcher']->addListener(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($callback) {
$this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
......@@ -316,7 +320,7 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
*/
public function finish($callback, $priority = 0)
{
$this['dispatcher']->addListener(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($callback) {
$this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($callback) {
call_user_func($callback, $event->getRequest(), $event->getResponse());
}, $priority);
}
......@@ -352,7 +356,7 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
*/
public function error($callback, $priority = -8)
{
$this['dispatcher']->addListener(KernelEvents::EXCEPTION, new ExceptionListenerWrapper($this, $callback), $priority);
$this->on(KernelEvents::EXCEPTION, new ExceptionListenerWrapper($this, $callback), $priority);
}
/**
......
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Silex\Tests;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
class LazyDispatcherTest extends \PHPUnit_Framework_TestCase
{
/** @test */
public function beforeMiddlewareShouldNotCreateDispatcherEarly()
{
$dispatcherCreated = false;
$app = new Application();
$app['dispatcher'] = $app->share($app->extend('dispatcher', function ($dispatcher, $app) use (&$dispatcherCreated) {
$dispatcherCreated = true;
return $dispatcher;
}));
$app->before(function () {});
$this->assertFalse($dispatcherCreated);
$request = Request::create('/');
$app->handle($request);
$this->assertTrue($dispatcherCreated);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment