Новое в Symfony 2.8: Symfony как микрофреймворк

  • 1 год назад

Микрофреймворк это термин, обозначающий «минималистичный фреймворк веб-приложений». Под этим словом разработчики обычно понимают «быстрые и небольшие фреймворки» - например, Silex. Но под минифреймфорками можно понимать также простые и более гибкие фреймворки, в которых вы можете воспользоваться различными архитектурными решениями.

Благодаря гибкой внутренней архитектуре, Symfony можно было использовать в качестве микрофреймворка с самого начала. Однако лишь немногие разработчики использовали Symfony таким образом, поскольку это было не совсем удобно.

Symfony 2.8 работает на основе новой технологии микроядра, что значительно упрощает создание однофайловых (и даже более мелких) приложений. Приложение Hello World, использующее Symfony в качестве микрофреймворка, выглядит следующим образом:

 <?php

// 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');
    }
}

Единственный класс MicroKernel включает бандлы, конфигурирует их, задает маршрутизацию и даже содержит код контроллера. Если исключить обязательные импорты use и объявления function, приведенный пример содержит ровно 4 строки кода PHP. Вы только вдумайтесь: полнофункциональное приложение Symfony всего в 4 строках кода!

Новое ядро не улучшает «сырую» работу Symfony, оно лишь меняет способ регистрации маршрутов и бандлов. Но поскольку вы активируете только те функции, которые вы используете, то многие функции и комплекты из стандартной версии Symfony (Standard Edition) деактивированы. Это и объясняет разницу, которую видна в работе приложения:

Лучшим в микрофреймворке Symfony является то, что вы создаете свое приложение на основе Symfony, то есть вы не столкнетесь с обычными ограничениями, присутствующими в микрофреймворках. По мере разрастания вашего приложения, вы можете использовать все чудесные функции и бандлы Symfony.

В следующем примере к приложению Hello World добавлена поддержка шаблонов из Twig, панель инструментов Web Debug и Symfony Profiler. В результате мы по-прежнему получаем однофайловое приложение:

 <?php
// 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');
    }
}

Но создание однофайловых приложений не является основной целью этого микроядра. Настоящий пример применения – это создание небольших приложений Symfony. Возможно, даже приложений с одним файлом services.yml, одним файлом config.yml на каждую среду и маршрутизацией, определенной как аннотации в обычных классах контроллера. Ниже приведен полный код, необходимый для создания описанного выше приложения:

<?php
// 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');
    }
}

И не забудьте обновить фронт-контроллер, чтобы он использовал новое микроядро вместо обычного AppKernel:

// 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();

Итак, если думаете, что выбрать – микрофреймворк или полноценный фреймворк, то у вас появилась новая возможность. Теперь одновременно в одном приложении вы можете использовать и тот, и другой, причем без потери каких-либо функций.

Комментарии

0