New in Symfony 2.8: Symfony as a Microframework
November 19, 2015 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
A microframework is a term used to refer to "minimalistic web application frameworks". Developers usually associate this term with "fast and small frameworks", such as Silex. But you can also think of microframeworks as simple and less-opinionated fameworks where you opt-in to the the architecture-related decisions.
Thanks to its flexible internal architecture, it has been possible to use Symfony as a microframework since day one. However, few developers have used Symfony in that way because it wasn't completely convenient.
Symfony 2.8 introduces a new microkernel trait to greatly simplify the creation of single-file (or just smaller) Symfony applications. A "Hello World" application using Symfony as a microframework looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// app/MicroKernel.php
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
class MicroKernel extends Kernel
{
use MicroKernelTrait;
public function registerBundles()
{
return array(new Symfony\Bundle\FrameworkBundle\FrameworkBundle());
}
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$routes->add('/', 'kernel:indexAction', 'index');
}
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
$c->loadFromExtension('framework', ['secret' => '12345']);
}
public function indexAction()
{
return new Response('Hello World');
}
}
A single MicroKernel
class enables the bundles, configures them, defines the
routing and even holds the controller code. If you exclude the mandatory use
imports and the function
declarations, the above example has exactly
4 lines of PHP code. Think about that for a moment: a fully-functional
Symfony application in just 4 lines of code!
The new microkernel doesn't improve the raw Symfony performance, because it just changes the way routes and bundles are registered. However, since you are only enabling the features you use, lots of the features and bundles of the Symfony Standard Edition are disabled. This explains the difference perceived in the application performance:
The best thing about the Symfony microframework is that you are building your application on the shoulders of Symfony, meaning that you won't face any of the usual restrictions of the microframeworks. All the incredible Symfony features and bundles are ready to use in case you need them as your application grows.
In the following example, the Hello World
application is expanded to add
Twig templating support, the Web Debug toolbar and the Symfony Profiler. The result
is still a single-file application:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
// app/MicroKernel.php
class MicroKernel extends Kernel
{
use MicroKernelTrait;
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'), true)) {
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
}
return $bundles;
}
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$routes->mount('/_wdt', $routes->import('@WebProfilerBundle/Resources/config/routing/wdt.xml'));
$routes->mount('/_profiler', $routes->import('@WebProfilerBundle/Resources/config/routing/profiler.xml'));
$routes->add('/', 'kernel:indexAction', 'index');
}
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
// load bundles' configuration
$c->loadFromExtension('framework', [
'secret' => '12345',
'profiler' => null,
'templating' => ['engines' => ['twig']],
]);
$c->loadFromExtension('web_profiler', ['toolbar' => true]);
// add configuration parameters
$c->setParameter('mail_sender', 'user@example.com');
// register services
$c->register('app.markdown', 'AppBundle\\Service\\Parser\\Markdown');
}
public function indexAction()
{
return $this->container->get('templating')->renderResponse('index.html.twig');
}
}
Creating single-file applications is not the main purpose of this microkernel.
The real use-case is to create smaller Symfony applications, perhaps having
just one services.yml
file, one config.yml
file per environment and the
routing defined as annotations in regular controller classes. This is the full
code needed to implement this use case:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// app/MicroKernel.php
// ...
class MicroKernel extends Kernel
{
use MicroKernelTrait;
public function registerBundles()
{
return array(
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new AppBundle\AppBundle(),
);
}
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$routes->mount('/', $routes->import('@AppBundle/Controller', 'annotation'));
}
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
$loader->load(__DIR__.'/config/services.yml');
}
}
And don't forget to update the front controller to use this new microkernel
instead of the usual AppKernel
:
1 2 3 4 5 6 7 8 9 10
// web/app.php
use Symfony\Component\HttpFoundation\Request;
$loader = require __DIR__.'/../app/autoload.php';
require_once __DIR__.'/../app/MicroKernel.php';
$app = new MicroKernel('prod', false);
$app->loadClassCache();
$app->handle(Request::createFromGlobals())->send();
So if you're choosing between a microframework or the full-stack framework, you have a new possibility. Now you can have both at the same time in the same application and without compromising any features.
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
What questions should guide our choices to determine whether to use Silex (for instance) or Symfony as a microframework in a project ?
How about a micro-edition with this Micro Kernel already set up and only the minimal requirements to boot a Symfony application ?
Silex is an implementation of a framework on top of the Symfony components (done in a very different way than Symfony, the full-stack framework; Pimple, ...).
Symfony MicroKernel is a "just" different way to **configure** the Symfony full-stack framework, but shares everything else (caching, bundles, ...).
Some API endpoints or other tasks that require little logic on the server spring to mind.
I have a Symfony App called Campus Discounts where I separate logic using requests such that GET requests are delivered promptly while POST requests are sent to a queue to be processed later. Depending on the POST action, an email might be sent, an API contacted, both or more. There are many bundles installed for these tasks. Is it my understanding that I can use the Symfony microframework to create a new app.php for GET requests removing unnecessary bundles that have nothing to do with displaying content thus having a leaner faster system but still have the bundles for another app_queue.php for processing code?
This is how I am seeing it so far and if so it excites me, not that my app is suffering from performance issues thanks to Blackfire :)
Anyways, being able to create multiple kernels easily is one of the side benefits of the MicroKernelTrait that I hadn't even thought about until recently :).
https://github.com/ikoene/symfony-micro
Once you get more business logic, I would recommend to go to Symfony full stack.