Pierstoval
11/23/2015 - 1:43 PM

One-file Symfony application

One-file Symfony application


# INFO:
# This file is optional and only copy/pasted from Symfony standard edition.
# It's needed if you need an apache support of the web entry point (index.php)

DirectoryIndex app.php
Options FollowSymlinks
<IfModule mod_negotiation.c>
    Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .? - [L]
    RewriteRule .? %{ENV:BASE}/app.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        RedirectMatch 302 ^/$ /app.php/
    </IfModule>
</IfModule>

Symfony application with one file

(ok, 2 files with composer.json and 3 if you need an .htaccess file...)

Now there's a MicroKernel class in Symfony 2.8 and it's awesome!

Advantages

Light

With 27 deep dependencies, it's much lighter than the whole Symfony framework (43 packages + symfony/security (4 packages) + 8 dependencies = 55 packages), and lighter again than the Symfony Standard edition (26 + Symfony framework = 81 packages).

It means that version constraints are certainly easier to manage as you only require the FrameworkBundle as base.

Also, it means that you can create simple web services or one-page apps that wouldn't require as many components as the standard edition (twig, monolog, swiftmailer, doctrine...), but with the scalability of Symfony bundles, without the more "exotic" Provider-based system in Silex (which uses a different Dependency Injection Container than Symfony).

Testing

This system is awesome: now, a single bundle is required (the FrameworkBundle) and you can test your own bundle inside it to be sure that your bundle is very scalable and flexible in terms of dependency, and more: standalone (as any bundle should be).

It means that you can develop components and bundles that are totally decoupled from Symfony itself and that require only a few components.

It's very good for community developers because it'll allow them to create "more real" applications with only one more dependency, their bundle, and test it to be sure it's compatible with any other big or small Symfony app.

No config

As the app is very tiny, you just need to allow the creation of the vendor, logs and cache dirs (which you won't use), and you can just need ONE file to generate this all.

Directory structure:

├── cache/
├── logs/
├── vendor/
└── web/
        .htaccess (optional)
    └── index.php
├── composer.json
├── composer.lock

You can add other files but basically it's as simple as that!

<?php

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

$autoloader = require __DIR__.'/../vendor/autoload.php';

class MicroKernel extends Kernel
{
    use MicroKernelTrait;

    public function getRootDir()
    {
        return realpath(__DIR__.'/../');
    }

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

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        $routes->add('/', 'kernel:indexAction', 'index');
    }

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
    }

    public function indexAction()
    {
        return new Response('Hello World');
    }
}

$app = new MicroKernel('prod', false);
$app->loadClassCache();
$app->handle(Request::createFromGlobals())->send();
{
    "require": {
        "symfony/framework-bundle": "^2.8"
    }
}