[HttpKernel] Move request-stashing behavior to the Kernel class

Previously, HttpKernel performed request-stashing.  By moving this to the Kernel class, the request is now available immediately after the kernel becomes aware of it.  If the kernel is allowed to boot lazily (during the first call to handle()), this also allows an actual master Request to be available during booting.

The old "request" service definition (with a bogus class name) can be replaced with a factory-aware definition that retrieves the request directly from the kernel.
This commit is contained in:
Jeremy Mikola 2010-12-08 19:04:47 -05:00 committed by Fabien Potencier
parent 2ff474fc3a
commit 7eea4882db
3 changed files with 84 additions and 2 deletions

View File

@ -37,7 +37,7 @@
your front controller (app.php) so that it passes an instance of
YourRequestClass to the Kernel.
-->
<service id="request" class="WillNeverBeCalled" />
<service id="request" factory-service="kernel" factory-method="getRequest" shared="false" />
<service id="response" class="%response.class%" shared="false" />
</services>

View File

@ -45,6 +45,7 @@ abstract class Kernel implements HttpKernelInterface, \Serializable
protected $booted;
protected $name;
protected $startTime;
protected $request;
const VERSION = '2.0.0-DEV';
@ -174,11 +175,29 @@ abstract class Kernel implements HttpKernelInterface, \Serializable
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$masterRequest = HttpKernelInterface::MASTER_REQUEST === $type ? $request : $this->request;
$this->request = $request;
if (false === $this->booted) {
$this->boot();
}
return $this->container->get('http_kernel')->handle($request, $type, $catch);
$response = $this->container->get('http_kernel')->handle($this->request, $type, $catch);
$this->request = $masterRequest;
return $response;
}
/**
* Gets the current request.
*
* @return Request
*/
public function getRequest()
{
return $this->request;
}
/**

View File

@ -12,6 +12,8 @@
namespace Symfony\Tests\Component\HttpKernel;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
class KernelTest extends \PHPUnit_Framework_TestCase
@ -22,6 +24,57 @@ class KernelTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo', $kernel->getSafeName());
}
public function testHandleSetsTheRequest()
{
$masterRequest = Request::create('/');
$subRequest = Request::create('/');
$httpKernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
->disableOriginalConstructor()
->setMethods(array('handle'))
->getMock();
$httpKernel->expects($this->at(0))
->method('handle')
->with($masterRequest);
$httpKernel->expects($this->at(1))
->method('handle')
->with($subRequest);
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
$container->expects($this->exactly(2))
->method('get')
->with('http_kernel')
->will($this->returnValue($httpKernel));
$kernel = $this->getMockBuilder('Symfony\Tests\Component\HttpKernel\KernelForTest')
->setConstructorArgs(array('dev', true, '-foo-'))
->setMethods(array('boot'))
->getMock();
$kernel->setContainer($container);
$testCase = $this;
$bootCallback = function() use ($masterRequest, $kernel, $testCase) {
$kernel->setBooted(true);
$testCase->assertSame($masterRequest, $kernel->getRequest(), '->handle() sets the Request before booting');
};
$kernel->expects($this->once())
->method('boot')
->will($this->returnCallback($bootCallback));
$kernel->handle($masterRequest);
$kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
$this->assertSame($masterRequest, $kernel->getRequest(), '->handle() restores the master Request after handling a sub-request');
}
}
class KernelForTest extends Kernel
@ -48,4 +101,14 @@ class KernelForTest extends Kernel
public function registerContainerConfiguration(LoaderInterface $loader)
{
}
public function setBooted($booted)
{
$this->booted = $booted;
}
public function setContainer($container)
{
$this->container = $container;
}
}