Why ?
Maybe because I want for some parts of the application to be really fast, and for the most of the application to enjoy the productivity of using a full stack framework and have access to all the third party bundles.
Of course having 2 application may introduce other kind of problems.
How my application should work:
- receive request
- fast Silex kernel handles the request.
- if the URL request is not matching any of the routes from Silex, it will return a response with status 404
- if the URL is matching a route, execute controller and get response
- check what is the response from Silex
- if the response has status 404 pass it to the Symfony kernel
- otherwise return response
Using the 2 frameworks together is possible because they both use the same abstraction for HTTP Request and Response and the HttpKernel.
There is a project called StackPHP that promotes interoperability between applications based on the HttpKernelInterface.
Implementation:
Create a probject folder under /var/www/public called double: /var/www/public/double
I will be using Symfony Standard Edition and Silex Skeleton project by Fabien Potencier: https://packagist.org/packages/fabpot/silex-skeleton
Install using Composer in two different subfolders:
composer create-project fabpot/silex-skeleton silex ~2.0@dev
composer create-project symfony/framework-standard-edition symf
Create a virtual host that will point to /var/www/public/double/symf/web
You may want to first save Symfony app.php and app_dev.php before editing them:
app_dev.php :
<?php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Debug\Debug; use Silex\Application; /** * @var Composer\Autoload\ClassLoader $loader */ $loader = require __DIR__.'/../app/autoload.php'; require_once __DIR__.'/../../silex/vendor/autoload.php'; Debug::enable(); //create request object $request = Request::createFromGlobals(); //initialize Silex app $app = require __DIR__.'/../../silex/src/app.php'; require __DIR__.'/../../silex/config/dev.php'; require __DIR__.'/../../silex/src/controllers.php';
//handle request with Silex app
$response = $app->handle($request);
if ($response->getStatusCode() === 404) {
//initialize Symfony app and handle request $kernel = new AppKernel('dev', true); $kernel->loadClassCache(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response); } else { $response->send(); $app->terminate($request, $response); }
Into app.php I've added microtime() function to get the loading time in production as I do not have access to the Web Profiler.
<?php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Silex\Application; $time_start = microtime(true); /** * @var Composer\Autoload\ClassLoader $loader */ $loader = require_once __DIR__.'/../app/autoload.php'; require_once __DIR__.'/../../silex/vendor/autoload.php'; //create request object $request = Request::createFromGlobals(); //initialize Silex app $app = require __DIR__.'/../../silex/src/app.php'; require __DIR__.'/../../silex/config/prod.php'; require __DIR__.'/../../silex/src/controllers.php'; $response = $app->handle($request); if ($response->getStatusCode() === 404) { $kernel = new AppKernel('prod', false); $kernel->loadClassCache(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response); $time_end = microtime(true); $time = $time_end - $time_start; echo "Execution time: $time seconds\n"; } else { $response->send(); $app->terminate($request, $response); $time_end = microtime(true); $time = $time_end - $time_start; echo "Execution time: $time seconds\n"; }
I did some simple tests using the production env (app.php) and generally Silex is 3 times faster than Symfony, which is no surprise as it is lighter.
In Silex I used Doctrine DBAL (not ORM), the provider it is included in the Silex Skeleton project, just needs to be configured in src/app.php:
$app->register(new DoctrineServiceProvider(), array( 'dbs.options' => array ( 'localhost' => array( 'driver' => 'pdo_mysql', 'host' => 'localhost', 'dbname' => 'symfony', 'user' => 'root', 'password' => 'root', 'charset' => 'utf8', ) ), ));