Как создать приложение Symfony с несколькими ядрами

Как создать приложение Symfony с несколькими ядрами

В большинстве приложений Symfony входящие запросы обрабатываются фронт контроллером web/app.php, который инстанциирует класс app/AppKernel.php для создания ядра приложения, загружающего пакеты и работающего с запросом лля генерирования ответа.

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

Вот наиболее распространённые случаи применения создания множества ядер:

  • Приложение, которое определяет API, может определить два ядра по причине производительности. Первое ядро будет служить обычному приложению, а второе - реагировать только на API запросы, загружая пакеты и подключая меньше функций;
  • Высокочувствительное приложение может также определять два ядра. Первое будет только загружать маршруты, совпадающие с публичными частями приложения. Второе - загружать остальное приложение и его доступ будет защищён веб-сервером;
  • Приложение, ориентированное на микросервисы, может определять несколько ядер для выборочного подключения или отключения сервисов, превращая традиционное монолитное приложение в несколько микро-приложений.

Добавление нового ядра в приложение

Создание нового ядра в приложении - это процесс, состоящий из трёх шагов:

  1. Создайте новый фронт контроллер для загрузки нового ядра;
  2. Создайте новый класс ядра;
  3. Определите конфигурацию, загружаемую новым ядром.

Следующий пример показывает, как создать новое ядро для API заданного приложения Symfony.

Шаг 1) Создайте новый фронт контроллер

Вместо создания нового фронт контроллера с нуля, легче будет дублировать уже существующие. Например, создайте web/api_dev.php из web/app_dev.php, а web/api.php из web/app.php.

Далее, обновите код нового фронт контроллера, чтобы инстанциировать новый класс ядра, вместо обычного класса AppKernel:

1
2
3
4
5
6
7
8
9
// web/api.php
// ...
$kernel = new ApiKernel('prod', false);
// ...

// web/api_dev.php
// ...
$kernel = new ApiKernel('dev', true);
// ...

Tip

Другой подход заключается в том, чтобы оставить существующий фронт контроллер (например, app.php и app_dev.php), но добавить утверждение if для загрузки другого ядра, основанного на URL (например, если URL начинается с``/api``, используйте ApiKernel).

Шаг 2) Создайте новый класс ядра

Теперь вам нужно определить класс ApiKernel, используемый новым фронт контроллером. Легче всего это сделать дублировав существующий файл app/AppKernel.php и внеся в него необходимые изменения.

В этом примере, ApiKernel будет загружать меньше пакетов, чем AppKernel. Убедитесь в том, что вы также изменили локацию кеша, логов и файлов конфигурации, чтобы они не сталкивались с файлами из AppKernel:

 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
// app/ApiKernel.php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class ApiKernel extends Kernel
{
    public function registerBundles()
    {
        // загружать только пакеты, строго необходимые для API...
    }

    public function getCacheDir()
    {
        return dirname(__DIR__).'/var/cache/api/'.$this->getEnvironment();
    }

    public function getLogDir()
    {
        return dirname(__DIR__).'/var/logs/api';
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load($this->getProjectDir().'/app/config/api/config_'.$this->getEnvironment().'.yml');
    }
}

Для того, чтобы автозагрузчик нашёл ваш новый ApiKernel, убедитесь в том, что вы добавили его в ваш раздел автозагрузки composer.json:

1
2
3
4
5
6
7
8
{
    "...": "..."

    "autoload": {
        "psr-4": { "": "src/" },
        "classmap": [ "app/AppKernel.php", "app/AppCache.php", "app/ApiKernel.php" ]
    }
}

Далее, запустите composer install, чтобы сбросить вашу новую конфигурацию автозагрузки.

Шаг 3) Определите конфигурацию ядра

Наконец, определите файлы конфигурации, которые будет загружать новый ApiKernel. Следуя коду выше, эта конфигурация будет жить в каталоге app/config/api/.

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

1
2
3
4
5
# app/config/api/config_dev.yml
imports:
    - { resource: ../config_dev.yml }

# override option values ...

Выполнение команд с другим ядром

Скрипт bin/console, используемый для запуска команд Symfony всегда использует класс по умолчанию AppKernel, чтобы построить приложение и загрузить команды. Если вам нужно выполнить консольные команды, используя новое ядро, дублируйте скрипт bin/console и переименуйте его (например, bin/api).

Далее, замените инстанциирование AppKernel вашим собственным инстанциированием ядра (например, ApiKernel) и теперь вы можете выполнять команды, используя новое ядро (например, php bin/api cache:clear). Тепеоь вы можете выполнять команды, используя новое ядро.

Note

Команды, доступные для каждого конспольного скрипта (например, bin/console и bin/api) могут отличаться, так как они зависят от пакетов, подключенных дла каждого ядра, которые могут отличаться.

Отображение шаблонов, определённых в другом ядре

Если вы следуете Лучшим практикам Symfony, то шаблоны нового ядра будут храниться в app/Resources/views/. Попытка отобразить эти шаблоны в другом ядре, приведут к ошибки Не существует зарегистрированных путей для пространста имён "__main__".

Чтобы решить эту проблему, добавьте следующую конфигурацию к вашему ядру:

1
2
3
4
5
# api/config/config.yml
twig:
    paths:
        # позволяет использова шаблоны app/Resources/views/ в ApiKernel
        "%kernel.project_dir%/app/Resources/views": ~

Добавление большего количества ядер в приложение

Если ваше приложеиие очень сложное и вы создаёте несколько ядер, то лучше хранить их в собственных каталогах, вместо того, чтобы путаться с кучей файлов в каталоге app/ по умолчанию:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
project/
├─ app/
│  ├─ ...
│  ├─ config/
│  └─ AppKernel.php
├─ api/
│  ├─ ...
│  ├─ config/
│  └─ ApiKernel.php
├─ ...
└─ web/
    ├─ ...
    ├─ app.php
    ├─ app_dev.php
    ├─ api.php
    └─ api_dev.php

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.