Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Configuration
  4. Building your own Framework with the MicroKernelTrait
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • A Single-File Symfony Application
  • The Methods of a "Micro" Kernel
  • Advanced Example: Twig, Annotations and the Web Debug Toolbar

Building your own Framework with the MicroKernelTrait

Edit this page

Warning: You are browsing the documentation for Symfony 3.4, which is no longer maintained.

Read the updated version of this page for Symfony 6.3 (the current stable version).

Building your own Framework with the MicroKernelTrait

A traditional Symfony app contains a sensible directory structure, various configuration files and an AppKernel with several bundles already-registered. This is a fully-featured app that's ready to go.

But did you know, you can create a fully-functional Symfony application in as little as one file? This is possible thanks to the new MicroKernelTrait. This allows you to start with a tiny application, and then add features and structure as you need to.

A Single-File Symfony Application

Start with a completely empty directory. Get symfony/symfony as a dependency via Composer:

1
$ composer require symfony/symfony

Next, create an index.php file that creates a kernel class and executes it:

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
// index.php
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

// require Composer's autoloader
require __DIR__.'/vendor/autoload.php';

class AppKernel extends Kernel
{
    use MicroKernelTrait;

    public function registerBundles()
    {
        return [
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle()
        ];
    }

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
        // PHP equivalent of config.yml
        $c->loadFromExtension('framework', [
            'secret' => 'S0ME_SECRET'
        ]);
    }

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        // kernel is a service that points to this class
        // optional 3rd argument is the route name
        $routes->add('/random/{limit}', 'kernel:randomAction');
    }

    public function randomAction($limit)
    {
        return new JsonResponse([
            'number' => rand(0, $limit)
        ]);
    }
}

$kernel = new AppKernel('dev', true);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

That's it! To test it, start the Symfony Local Web Server:

1
$ symfony server:start

Then see the JSON response in your browser:

http://localhost:8000/random/10

The Methods of a "Micro" Kernel

When you use the MicroKernelTrait, your kernel needs to have exactly three methods that define your bundles, your services and your routes:

registerBundles()
This is the same registerBundles() that you see in a normal kernel.
configureContainer(ContainerBuilder $c, LoaderInterface $loader)
This method builds and configures the container. In practice, you will use loadFromExtension to configure different bundles (this is the equivalent of what you see in a normal config.yml file). You can also register services directly in PHP or load external configuration files (shown below).
configureRoutes(RouteCollectionBuilder $routes)
Your job in this method is to add routes to the application. The RouteCollectionBuilder has methods that make adding routes in PHP more fun. You can also load external routing files (shown below).

Advanced Example: Twig, Annotations and the Web Debug Toolbar

The purpose of the MicroKernelTrait is not to have a single-file application. Instead, its goal to give you the power to choose your bundles and structure.

First, you'll probably want to put your PHP classes in an src/ directory. Configure your composer.json file to load from there:

1
2
3
4
5
6
7
8
9
10
{
    "require": {
        "...": "..."
    },
    "autoload": {
        "psr-4": {
            "": "src/"
        }
    }
}

Then, run composer dump-autoload to dump your new autoload config.

Now, suppose you want to use Twig and load routes via annotations. Instead of putting everything in index.php, create a new app/AppKernel.php to hold the kernel. Now it 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// app/AppKernel.php
use Doctrine\Common\Annotations\AnnotationRegistry;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

// require Composer's autoloader
$loader = require __DIR__.'/../vendor/autoload.php';
// auto-load annotations
AnnotationRegistry::registerLoader([$loader, 'loadClass']);

class AppKernel extends Kernel
{
    use MicroKernelTrait;

    public function registerBundles()
    {
        $bundles = [
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
        ];

        if ($this->getEnvironment() == 'dev') {
            $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
        }

        return $bundles;
    }

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
        $loader->load(__DIR__.'/config/config.yml');

        // configure WebProfilerBundle only if the bundle is enabled
        if (isset($this->bundles['WebProfilerBundle'])) {
            $c->loadFromExtension('web_profiler', [
                'toolbar' => true,
                'intercept_redirects' => false,
            ]);
        }
    }

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        // import the WebProfilerRoutes, only if the bundle is enabled
        if (isset($this->bundles['WebProfilerBundle'])) {
            $routes->import('@WebProfilerBundle/Resources/config/routing/wdt.xml', '/_wdt');
            $routes->import('@WebProfilerBundle/Resources/config/routing/profiler.xml', '/_profiler');
        }

        // load the annotation routes
        $routes->import(__DIR__.'/../src/Controller/', '/', 'annotation');
    }

    // optional, to use the standard Symfony cache directory
    public function getCacheDir()
    {
        return __DIR__.'/../var/cache/'.$this->getEnvironment();
    }

    // optional, to use the standard Symfony logs directory
    public function getLogDir()
    {
        return __DIR__.'/../var/logs';
    }
}

3.4

Support for annotation routing without an external bundle was introduced in Symfony 3.4. Prior to version 3.4, you needed to install the SensioFrameworkExtraBundle.

Unlike the previous kernel, this loads an external app/config/config.yml file, because the configuration started to get bigger:

1
2
3
4
5
6
# app/config/config.yml
framework:
    secret: S0ME_SECRET
    templating:
        engines: ['twig']
    profiler: { only_exceptions: false }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:framework="http://symfony.com/schema/dic/symfony"
    xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

    <framework:config secret="S0ME_SECRET">
        <framework:templating>
            <framework:engine>twig</framework:engine>
        </framework:templating>
        <framework:profiler only-exceptions="false"/>
    </framework:config>
</container>
1
2
3
4
5
6
7
8
9
10
// app/config/config.php
$container->loadFromExtension('framework', [
    'secret' => 'S0ME_SECRET',
    'templating' => [
        'engines' => ['twig'],
    ],
    'profiler' => [
        'only_exceptions' => false,
    ],
]);

This also loads annotation routes from an src/Controller/ directory, which has one file in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Controller/MicroController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;

class MicroController extends Controller
{
    /**
     * @Route("/random/{limit}")
     */
    public function randomAction($limit)
    {
        $number = rand(0, $limit);

        return $this->render('micro/random.html.twig', [
            'number' => $number
        ]);
    }
}

Template files should live in the Resources/views directory of whatever directory your kernel lives in. Since AppKernel lives in app/, this template lives at app/Resources/views/micro/random.html.twig:

1
2
3
4
5
6
7
8
9
10
<!-- app/Resources/views/micro/random.html.twig -->
<!DOCTYPE html>
<html>
    <head>
        <title>Random action</title>
    </head>
    <body>
        <p>{{ number }}</p>
    </body>
</html>

Finally, you need a front controller to boot and run the application. Create a web/index.php:

1
2
3
4
5
6
7
8
9
10
// web/index.php
use Symfony\Component\HttpFoundation\Request;

require __DIR__.'/../app/AppKernel.php';

$kernel = new AppKernel('dev', true);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

That's it! This /random/10 URL will work, Twig will render, and you'll even get the web debug toolbar to show up at the bottom. The final structure looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
your-project/
├─ app/
|  ├─ AppKernel.php
│  ├─ config/
│  └─ Resources
|     └─ views
|        └─ micro
|           └─ random.html.twig
├─ src/
│  └─ App
|     └─ Controller
|        └─ MicroController.php
├─ var/
|  ├─ cache/
│  └─ logs/
├─ vendor/
│  └─ ...
├─ web/
|  └─ index.php
├─ composer.json
└─ composer.lock

As before you can use the Symfony Local Web Server:

1
2
cd web/
$ symfony server:start

Then visit the page in your browser:

http://localhost:8000/random/10

Hey, that looks a lot like a traditional Symfony application! You're right: the MicroKernelTrait is still Symfony: but you can control your structure and features with less boilerplate configuration and code.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:
    Measure & Improve Symfony Code Performance

    Measure & Improve Symfony Code Performance

    Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).

    Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of Sylvain, a Symfony contributor

    Thanks Sylvain for being a Symfony contributor

    4 commits • 29 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony

    Search by Meilisearch