Commit 5187c9e6 authored by Fabien Potencier's avatar Fabien Potencier

added support for mountable applications

parent fa1a8005
......@@ -12,7 +12,7 @@ controller definitions, call the ``run`` method on your application.
::
require __DIR__.'/silex.phar';
require_once __DIR__.'/silex.phar';
use Silex\Application;
......@@ -380,6 +380,43 @@ correctly, to prevent Cross-Site-Scripting attacks.
);
});
Reusing applications
--------------------
To make your applications reusable, return the ``$app`` variable instead of
calling the ``run()`` method::
// blog.php
require_once __DIR__.'/silex.phar';
$app = new Silex\Application();
// define your blog app
$app->get('/post/{id}', function ($id) { ... });
// return the app instance
return $app;
Running this application can now be done like this::
$app = require __DIR__.'/blog.php';
$app->run();
This pattern allows you to easily "mount" this application under any other
one::
$blog = require __DIR__.'/blog.php';
$app = new Application();
$app->mount('/blog', $blog);
// define your main app
$app->run();
Now, blog posts are available under the ``/blog/post/{id}`` route, along side
any other routes you might have defined.
Pitfalls
--------
......
......@@ -255,6 +255,18 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
return htmlspecialchars($text, ENT_COMPAT, 'UTF-8');
}
/**
* Mounts an application under the given route prefix.
*
* @param string $prefix The route prefix
* @param Application|\Closure $app An Application instance or a Closure that returns an Application instance
*/
public function mount($prefix, $app)
{
$prefix = rtrim($prefix, '/');
$this->match($prefix.'/{path}', $app)->assert('path', '.*')->value('prefix', $prefix);
}
/**
* Handles the request and deliver the response.
*
......@@ -274,6 +286,21 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
return $this['kernel']->handle($request, $type, $catch);
}
/**
* Handles a Request when this application has been mounted under a prefix.
*
* @param Request $request A Request instance
* @param string $path The path info (without the prefix)
*/
public function __invoke(Request $request, $prefix)
{
foreach ($this['controllers']->all() as $controller) {
$controller->getRoute()->setPattern(rtrim($prefix, '/').$controller->getRoute()->getPattern());
}
return $this->handle($request);
}
/**
* Handles onCoreRequest events.
*/
......
......@@ -12,6 +12,8 @@
namespace Silex\Tests;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Functional test cases.
......@@ -39,4 +41,32 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('homepage'));
$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('foo_abc'));
}
public function testMount()
{
$mounted = new Application();
$mounted->get('/{name}', function ($name) { return new Response($name); });
$app = new Application();
$app->mount('/hello', $mounted);
$response = $app->handle(Request::create('/hello/Silex'));
$this->assertEquals('Silex', $response->getContent());
}
public function testLazyMount()
{
$mounted = function (Request $request, $prefix) {
$mounted = new Application();
$mounted->get('/{name}', function ($name) { return new Response($name); });
return $mounted($request, $prefix);
};
$app = new Application();
$app->mount('/hello', $mounted);
$response = $app->handle(Request::create('/hello/Silex'));
$this->assertEquals('Silex', $response->getContent());
}
}
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