Как работают маршруты в PHP фреймворке Symfony
Основы маршрутизации в Symfony
Как создать контроллер с маршрутом с помощью атрибутов?
// src/Controller/ProductController.php
namespace App\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
class ProductController
{
#[Route('/api/products', name: 'api_products', methods: ['GET'])]
public function list(): JsonResponse
{
return new JsonResponse(['products' => []]);
}
}Это современный способ определения маршрутов, доступный с Symfony 5.3 и PHP 8. Атрибут #[Route] позволяет задать путь, имя и ограничения. Метод возвращает JSON-ответ.
Типичная ошибка: маршрут не находится. Решение: очистить кэш командой php bin/console cache:clear или php bin/console cache:warmup. Также необходимо проверить, что используется PHP 8.
Как определить маршруты в YAML файле?
# config/routes.yaml
api_products:
path: /api/products
controller: App\Controller\ProductController::list
methods: GETВнешняя конфигурация маршрутов в YAML удобна для централизованного управления. Путь задается в path, контроллер указывает на метод. Ограничения по HTTP-методу задаются ключом methods.
Ошибки: неверный синтаксис YAML, несовпадение имени контроллера. После изменений необходимо перезагрузить кэш маршрутов.
Как использовать аннотации для маршрутов (устаревший способ)?
// src/Controller/ProductController.php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ProductController
{
/**
* @Route('/api/products', name='api_products', methods={'GET'})
*/
public function list(): JsonResponse
{
return new JsonResponse([]);
}
}Этот вариант работал в Symfony до 5.3, теперь рекомендуется переходить на атрибуты. Требуется установка sensio/framework-extra-bundle.
В Symfony 7 аннотации удалены, при обновлении возникнут ошибки. Рекомендуется мигрировать на атрибуты с помощью инструментов обновления.
Как зарегистрировать контроллер как сервис и задать маршрут?
# config/services.yaml
services:
App\Controller\ProductController:
tags: ['controller.service_arguments']
# config/routes.yaml
api_products:
path: /api/products
controller: App\Controller\ProductController::list
methods: GETКонтроллер регистрируется как сервис с тегом controller.service_arguments. Это дает возможность внедрять зависимости напрямую в конструктор. Однако в современных версиях это делается автоматически.
Если не указать тег, маршрут не сработает. Также возможна путаница с именем сервиса.
Расширенные примеры маршрутизации
Параметры маршрута и их ограничения
// src/Controller/ProductController.php
#[Route('/api/products/{id}', name: 'api_product_show', requirements: ['id' => '\d+'])]
public function show(int $id): JsonResponse
{
return new JsonResponse(['id' => $id]);
}GET /api/products/42 -> 200 OK, тело: {'id':42}Параметр {id} передаётся в аргумент метода. Ограничение requirements проверяет, что id состоит только из цифр.
Групповые маршруты через атрибут на классе
#[Route('/admin', name: 'admin_')]
class AdminController
{
#[Route('/dashboard', name: 'dashboard')]
public function dashboard(): Response { ... }
#[Route('/users', name: 'users')]
public function users(): Response { ... }
}Маршрут admin_dashboard ведет на /admin/dashboard Маршрут admin_users ведет на /admin/users
Префикс /admin добавляется ко всем маршрутам класса, а имя маршрута получает префикс admin_.
Ограничение HTTP-методов
#[Route('/api/products', name: 'api_products', methods: ['GET', 'POST'])]
public function collection(): JsonResponse { ... }GET /api/products - работает POST /api/products - работает DELETE /api/products - 405 Method Not Allowed
Методы задаются массивом. Можно также использовать отдельные атрибуты #[Get] и #[Post] (в Symfony 6+).
Значения по умолчанию для параметров
#[Route('/page/{page}', name: 'page', defaults: ['page' => 1])]
public function page(int $page): Response
{
// $page = 1, если не указан /page
}Если параметр не передан, используется значение из defaults.
Отладка маршрутов
=> php bin/console debug:router
------------------ -------- -------- ------ -----------------------------------
Name Method Scheme Host Path
------------------ -------- -------- ------ -----------------------------------
api_products GET ANY ANY /api/products
api_product_show GET ANY ANY /api/products/{id}
admin_dashboard GET ANY ANY /admin/dashboard
admin_users GET ANY ANY /admin/users
------------------ -------- -------- ------ -----------------------------------Команда debug:router выводит все зарегистрированные маршруты. Полезна для проверки имён и путей.