Архитектура

Архитектура

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

Понимание структуры каталогов

Структура каталогов приложения Symfony достаточно гибкая, но рекомендуемая структура выглядит следующим образом:

app/
Конфигурация приложения, шаблоны и переводы.
bin/
Исполняемые файлы (например, bin/console).
src/
PHP-код проекта.
tests/
Автоматические тестые (например, блочные тесты).
var/
Сгенерированные файлы (кеш, логи и т.д.).
vendor/
Сторонние зависимости.
web/
Корневой каталог веб-сервера.

Каталог web/

Корневой каталог веб-сервера - это дом всех публичных и статических файлов вроде изображений, таблиц стилей и файлов JavaScript. Это также место, где живет каждый контроллер (файл, который занимается всеми запросами к вашему приложению), например контроллер производства:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// web/app.php
require_once __DIR__.'/../var/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';

use Symfony\Component\HttpFoundation\Request;

$kernel = new AppKernel('prod', false);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();

Вначале контроллер инициализирует приложение, используя класс ядра (в этом случае AppKernel). Потом он создаёт объект Request, используя глобальные переменные PHP и передает их ядру. Последний шаг - отправить содержимое ответа, возвращенного ядром, обратно пользователю.

Каталог app/

Класс AppKernel - основная точка входа конфигурации приложения и как таковая, она сберегается в каталоге app/.

Этот класс должен реализовывать два метода:

registerBundles()
Должен вернуть массив всех пакетов, необходимых для запуска приложения, как буде объяснено в следующем разделе.
registerContainerConfiguration()
Загружает конфигурацию приложения (подробнее об этом будет позже).

Автозагрузка выполняется автоматически с помощью Composer, что означает, что вы можете использовать любой PHP-класс абсолютно ничего не делая! Все зависимости хранятся в каталоге vendor/, но это только соглашение. Вы можете сохранять их где угодно, глобально на вашем сервере или локально в ваших проектах.

Понимание системы пакетов

Этот раздел знакомит вас с одной из самых лучших и мощных функций Symfony: системой пакетов.

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

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

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

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

Регистрация пакета

Приложение состоит из пакетов, как определено в методе registerBundles() класса AppKernel. Каждый пакет - это каталог, который содержит единый класс пакета, описывающий его:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
        new Symfony\Bundle\SecurityBundle\SecurityBundle(),
        new Symfony\Bundle\TwigBundle\TwigBundle(),
        new Symfony\Bundle\MonologBundle\MonologBundle(),
        new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
        new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
        new Symfony\Bundle\AsseticBundle\AsseticBundle(),
        new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
        new AppBundle\AppBundle(),
    );

    if (in_array($this->getEnvironment(), array('dev', 'test'))) {
        $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
        $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
        $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
    }

    return $bundles;
}

В дополвнение к AppBundle, о котором уже шла речь, заметьте, что ядро также активирует другие пакеты, которые являются частью Symfony, например такие как FrameworkBundle, DoctrineBundle, SwiftmailerBundle и AsseticBundle.

Конфигурируем пакет

Каждый пакет можно настроить с помощью файлов конфигурации, написанных на YAML, XML, или PHP. Посмотрите на этот пример конфигурации Symfony по умолчанию:

 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
# app/config/config.yml
imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: services.yml }

framework:
    #esi:             ~
    #translator:      { fallbacks: ['%locale%'] }
    secret:          '%secret%'
    router:
        resource: '%kernel.project_dir%/app/config/routing.yml'
        strict_requirements: '%kernel.debug%'
    form:            true
    csrf_protection: true
    validation:      { enable_annotations: true }
    templating:      { engines: ['twig'] }
    default_locale:  '%locale%'
    trusted_proxies: ~
    session:         ~

# Twig Configuration
twig:
    debug:            '%kernel.debug%'
    strict_variables: '%kernel.debug%'

# Swift Mailer Configuration
swiftmailer:
    transport: '%mailer_transport%'
    host:      '%mailer_host%'
    username:  '%mailer_user%'
    password:  '%mailer_password%'
    spool:     { type: memory }

# ...

Каждая запись первого уровня вроде framework, twig и swiftmailer определяет конфигурацию конкретного пакета. Например, framework конфигурирует FrameworkBundle, в то время как swiftmailer конфигурирует SwiftmailerBundle.

Каждое окружение может переписать конфигурацию по умолчанию, путем предоставления особенного файла конфигурации. Например, окружение dev загружает файл config_dev.yml, который загружает главную конфигурацию (т.е. config.yml) и потом изменяет ее, чтобы добавить некоторые инструменты отладки:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# app/config/config_dev.yml
imports:
    - { resource: config.yml }

framework:
    router:   { resource: '%kernel.project_dir%/app/config/routing_dev.yml' }
    profiler: { only_exceptions: false }

web_profiler:
    toolbar: true
    intercept_redirects: false

# ...

Расширение пакета

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

Логические имена файлов

Когда вы хотите сослаться на файл из пакета, используйте эту нотацию: @BUNDLE_NAME/path/to/file; Symfony направит @BUNDLE_NAME к настоящему пути к пакету. Например, логический путь @AppBundle/Controller/DefaultController.php будет конвертирован в src/AppBundle/Controller/DefaultController.php, так как Symfony знает место размещения AppBundle.

Логические имена контроллеров

Для контроллеров, вам нужно ссылаться на действия, используя формат BUNDLE_NAME:CONTROLLER_NAME:ACTION_NAME. Например, AppBundle:Default:index отображает метод indexAction() из класса AppBundle\Controller\DefaultController.

Расширение пакетов

Если вы следуете этим соглашениям, тогда вы можете использовать наследование пакетов для переопределения файлов, контроллеров или шаблонов. Например, вы можете создать пакет NewBundle и указать, что он замещает AppBundle. Когда Symfony загружает контроллер AppBundle:Default:index, вначале будет поиск класса DefaultController в NewBundle и, если он не существует, тогда поиск продолжится в AppBundle. Это означает, что один пакет может заместить почти любую часть другого пакета!

Теперь вы понимаете, почему Symfony такая гибкая? Разделяйте ваши пакеты между приложениями, храните их локально или глобально - выбор за вами.

Использование поставщиков

Скорее всего ваше приложение будет зависеть от сторонних библиотек. Они должны храниться в каталоге vendor/. Никогда не трогайте ничего в этом каталоге, так как она управляется только Composer. Этот каталог уже содержит библиотеки Symfony, библиотеку SwiftMailer, Doctrine ORM, шаблонизатор Twig и некоторые другие сторонние библиотеки и пакеты.

Понмание кеша и логов

Приложения Symfony могут содержать несколько файлов конфигурации, определенных в нескольких форматах (YAML, XML, PHP, и т.д.). Вместо того, чтобы разбирать и комбинировать все эти файлы для каждого запроса, конфигурация приложения разбирается и анализируется только для самого первого запроса и потом компилируется в простой PHP-код, который хранится в каталоге var/cache/.

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

1
$ php bin/console cache:clear --env=prod

Во время разработки веб-приложения, много что может пойти не так. Файлы логов в каталоге var/logs/ сообщат вам все о запросах и помогут быстро исправить проблему.

Использовние интерфейса командной строки

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

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

1
$ php bin/console

Опция --help помогает вам узнать о применении команды:

1
$ php bin/console debug:router --help

Заключение

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

Это все, что входит в быстрый тур. От тестирования до отправки почты, вам все еще предстоит многое узнать, чтобы стать мастером Symfony. Готовы закопаться в эти темы сейчас? Не ищите дальще - переходите на официальную стартовую страницу и выбирайте любую понравившуюся вам тему.

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