Symfony — не монолитный фреймворк, а набор из 50+ самостоятельных компонентов. На экзамене проверяют понимание разницы между component, bundle и bridge, знание ключевых компонентов и их назначения.
Архитектура Symfony
Три типа пакетов
┌─────────────────────────────────────────────┐
│ Symfony Application │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Bundle │ │ Bundle │ │ Bundle │ │
│ │(TwigBundle│ │(Security │ │(Doctrine │ │
│ │ )│ │ Bundle) │ │ Bundle) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌────┴─────┐ ┌────┴─────┐ ┌────┴─────┐ │
│ │ Bridge │ │Component │ │ Bridge │ │
│ │(TwigBridge│ │(Security)│ │(Doctrine │ │
│ │ )│ │ │ │ Bridge) │ │
│ └────┬─────┘ └──────────┘ └────┬─────┘ │
│ │ │ │
│ ┌────┴─────┐ ┌────┴─────┐ │
│ │ 3rd party│ │ 3rd party │ │
│ │ (Twig) │ │ (Doctrine)│ │
│ └──────────┘ └──────────┘ │
└───────────────────────────────────────────────┘
Сравнение типов
| Характеристика | Component | Bundle | Bridge |
|---|---|---|---|
| Самостоятельный | Да | Нет | Нет |
| Нужен FrameworkBundle | Нет | Да | Нет |
| Установка без Symfony | Да | Нет | Зависит |
| Конфигурация | Программная | YAML/XML/PHP | Программная |
| Примеры | HttpFoundation, Console |
TwigBundle, SecurityBundle |
TwigBridge, DoctrineBridge |
Components (компоненты)
Компонент — самостоятельная PHP-библиотека, решающая конкретную задачу. Можно использовать в любом PHP-проекте без Symfony Framework.
<?php
declare(strict_types=1);
// Using Symfony Component WITHOUT Symfony Framework
// Just install: composer require symfony/http-foundation
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$name = $request->query->get('name', 'World');
$response = new Response(
content: sprintf('Hello %s!', htmlspecialchars($name)),
status: Response::HTTP_OK,
headers: ['Content-Type' => 'text/plain'],
);
$response->send();
Ключевые компоненты Symfony
Ядро (Core)
| Компонент | Назначение | Standalone |
|---|---|---|
HttpFoundation |
Request/Response объекты | Да |
HttpKernel |
Обработка запросов, events pipeline | Да |
Routing |
Маршрутизация URL → Controller | Да |
DependencyInjection |
DI-контейнер (PSR-11) | Да |
EventDispatcher |
Система событий (PSR-14) | Да |
Config |
Загрузка и валидация конфигурации | Да |
Ввод/Вывод
| Компонент | Назначение | Standalone |
|---|---|---|
Console |
CLI-команды | Да |
Form |
Создание и обработка HTML-форм | Да |
Validator |
Валидация данных | Да |
Serializer |
Сериализация/десериализация | Да |
Безопасность и аутентификация
| Компонент | Назначение | Standalone |
|---|---|---|
Security |
Аутентификация и авторизация | Частично |
PasswordHasher |
Хэширование паролей | Да |
RateLimiter |
Ограничение частоты запросов | Да |
Инфраструктура
| Компонент | Назначение | Standalone |
|---|---|---|
Messenger |
Очереди сообщений | Да |
Mailer |
Отправка email | Да |
Notifier |
Уведомления (SMS, Slack, etc.) | Да |
Cache |
Кэширование (PSR-6, PSR-16) | Да |
HttpClient |
HTTP-клиент (PSR-18) | Да |
Lock |
Блокировки для concurrency | Да |
Scheduler |
Планирование задач (cron) | Да |
Утилиты
| Компонент | Назначение | Standalone |
|---|---|---|
Filesystem |
Операции с файловой системой | Да |
Finder |
Поиск файлов и директорий | Да |
Process |
Запуск внешних процессов | Да |
String |
Работа со строками (Slugger, etc.) | Да |
Uid |
UUID, ULID генерация | Да |
Yaml |
Парсинг YAML | Да |
ExpressionLanguage |
Выражения и условия | Да |
PropertyAccess |
Доступ к свойствам объектов | Да |
Подвох экзамена: Все компоненты Symfony можно использовать standalone. Однако для полноценной интеграции в Symfony-приложение нужен Bundle. Если вопрос спрашивает "можно ли использовать HttpFoundation вне Symfony" — ответ: да, это standalone-компонент.
Bundles (бандлы)
Bundle — это плагин для Symfony-приложения. Он интегрирует компоненты и библиотеки в фреймворк: регистрирует сервисы, добавляет конфигурацию, предоставляет команды.
<?php
declare(strict_types=1);
namespace App;
// Bundles are registered in config/bundles.php
// config/bundles.php
return [
// Core framework — always required
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
// Template engine
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
// Database ORM
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
// Security
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
// Dev tools — only in dev/test
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
];
Структура бандла
<?php
declare(strict_types=1);
namespace Acme\BlogBundle;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
// Symfony 7+/8.0: AbstractBundle is the recommended base class
class AcmeBlogBundle extends AbstractBundle
{
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->scalarNode('api_key')->isRequired()->end()
->integerNode('cache_ttl')->defaultValue(3600)->end()
->end()
;
}
public function loadExtension(
array $config,
ContainerConfigurator $container,
ContainerBuilder $builder,
): void {
$container->services()
->set('acme_blog.api_client', ApiClient::class)
->args([$config['api_key'], $config['cache_ttl']])
->autowire()
;
}
}
Symfony 8.0:
AbstractBundleполностью заменяет старыеBundle+Extension+Configuration. Методыconfigure()иloadExtension()объединяют конфигурацию и загрузку сервисов в одном классе. Старый подход с отдельной Extension deprecated.
Ключевые бандлы Symfony
| Bundle | Зависит от | Предоставляет |
|---|---|---|
FrameworkBundle |
HttpKernel, DI, Routing, etc. | Базовый фреймворк, контроллеры |
TwigBundle |
TwigBridge, Twig | Шаблонизация |
SecurityBundle |
Security component | Аутентификация, авторизация |
WebProfilerBundle |
Profiler, TwigBundle | Debug toolbar, profiler |
MonologBundle |
Monolog | Логирование |
DebugBundle |
VarDumper | dump() функция |
MakerBundle |
Console | Генерация кода (make:controller, etc.) |
Bridges (мосты)
Bridge — адаптер между компонентом Symfony и сторонней библиотекой. Он обеспечивает интеграцию без жёсткой связи.
<?php
declare(strict_types=1);
// Example: TwigBridge connects Symfony components with Twig library
// It provides:
// - Twig extensions for Symfony (routing, forms, security)
// - Form theme rendering
// - Translation integration
// DoctrineBridge connects Symfony with Doctrine
// It provides:
// - Form types for Doctrine entities
// - Validator constraints
// - Security user provider
// - Data collectors for profiler
// MonologBridge connects Symfony with Monolog
// It provides:
// - Processors for request data
// - Handlers for Symfony-specific logging
Полная цепочка на примере Twig
Twig (3rd-party library)
↑ uses
TwigBridge (Symfony ↔ Twig integration)
↑ configured by
TwigBundle (registers services, adds config, provides Twig in Symfony app)
↑ used by
Symfony Application
# Installing Twig — what Flex installs:
composer require twig
# Actually installs:
# - twig/twig (3rd-party library)
# - symfony/twig-bridge (integration)
# - symfony/twig-bundle (framework integration)
# - twig/extra-bundle (extra Twig extensions)
Полная цепочка на примере Doctrine
doctrine/orm + doctrine/dbal (3rd-party library)
↑ uses
symfony/doctrine-bridge (Symfony ↔ Doctrine integration)
↑ configured by
doctrine/doctrine-bundle (registers services, adds config)
doctrine/doctrine-migrations-bundle (migration commands)
↑ used by
Symfony Application
Подвох экзамена: Bridge НЕ зависит от FrameworkBundle — он работает на уровне компонентов. Это позволяет использовать Bridge и в standalone-проектах. Например, TwigBridge можно использовать без TwigBundle, если вы интегрируете Twig с Symfony Forms в не-Symfony проекте.
Создание собственного бандла
<?php
declare(strict_types=1);
namespace Acme\PaymentBundle;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class AcmePaymentBundle extends AbstractBundle
{
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->scalarNode('gateway')
->isRequired()
->validate()
->ifNotInArray(['stripe', 'paypal', 'braintree'])
->thenInvalid('Invalid gateway %s')
->end()
->end()
->scalarNode('api_key')->isRequired()->end()
->booleanNode('sandbox')->defaultTrue()->end()
->end()
;
}
public function loadExtension(
array $config,
ContainerConfigurator $container,
ContainerBuilder $builder,
): void {
// Load services definition
$container->import('../config/services.yaml');
// Set parameters from config
$container->parameters()
->set('acme_payment.gateway', $config['gateway'])
->set('acme_payment.sandbox', $config['sandbox'])
;
}
}
Соглашения именования бандлов
| Правило | Пример правильно | Пример неправильно |
|---|---|---|
Суффикс Bundle |
AcmePaymentBundle |
AcmePayment |
| Vendor prefix | AcmePaymentBundle |
PaymentBundle |
| Имя класса = имя папки | AcmePaymentBundle/ |
Payment/ |
Компоненты для сертификации
На экзамене чаще всего спрашивают эти компоненты:
<?php
declare(strict_types=1);
// HttpFoundation — Request/Response abstraction
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
// HttpKernel — request handling pipeline
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
// Routing — URL matching and generation
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
// DependencyInjection — service container
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
// EventDispatcher — event system
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
// Validator — data validation
use Symfony\Component\Validator\Constraints as Assert;
// Security — authentication/authorization
use Symfony\Component\Security\Http\Attribute\IsGranted;
Подвох экзамена:
HttpKernel\Exception\*— это HTTP-специфичные исключения.NotFoundHttpExceptionавтоматически конвертируется в 404 ответ,AccessDeniedHttpException— в 403. Не путайте с обычными PHP-исключениями. Symfony перехватываетHttpExceptionInterfaceвkernel.exceptionи создаёт соответствующий Response.