Роутинг і контролери

← Роутинг і контролери

Ashterix

docs(articles): SEO titles, intros and a section preview image for From Magento to Symfony

uk/articles/magento-to-symfony/core/routing.md +6 −0

Роутинг і контролери

Маршрути в Symfony описують атрибутом #[Route] прямо на методі контролера, без routes.xml і окремого класу на кожну дію. Аргументи дії — сутності, DTO, сервіси — підставляються автоматично.

Magento · routes.xml + Controller/Question/View.php

<router id="standard">
    <route id="faq" frontName="faq">
        <module name="Vendor_Faq"/>
    </route>
</router>
class View implements HttpGetActionInterface
{
    public function __construct(
        private RequestInterface $request,
        private QuestionRepositoryInterface $questions,
        private PageFactory $pageFactory,
    ) {}

    public function execute(): ResultInterface
    {
        $id = (int) $this->request->getParam('id');
        $question = $this->questions->getById($id);
        $page = $this->pageFactory->create();
        $page->getConfig()->getTitle()->set($question->getTitle());
        return $page;
    }
}

Symfony · src/Controller/FaqController.php

use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\Routing\Attribute\Route;

final class FaqController extends AbstractController
{
    #[Route('/faq', name: 'faq_index', methods: ['GET'])]
    public function index(QuestionRepository $questions): Response
    {
        return $this->json($questions->findActive());
    }

    #[Route('/faq/{slug}', name: 'faq_show', methods: ['GET'])]
    public function show(
        #[MapEntity(mapping: ['slug' => 'slug'])]
        Question $question,
    ): Response
    {
        return $this->json($question);
    }
}
  • Сутність підставляється за параметром маршруту; якщо її немає, буде 404 без жодного коду. Для {id} атрибут #[MapEntity] не потрібен.
  • Сервіси можна просити прямо в аргументах дії, а не лише в конструкторі.
  • URL генерують за іменем маршруту: $this->generateUrl('faq_show', ['slug' => $q->getSlug()]).
  • bin/console debug:router — усі маршрути, router:match /faq/returns — який маршрут спрацює.

JSON на вході: замість getParam()

Symfony · DTO з тіла запиту з валідацією

final class CreateQuestion
{
    public function __construct(
        #[Assert\NotBlank, Assert\Length(max: 255)]
        public readonly string $title,
        #[Assert\NotBlank]
        public readonly string $answer,
    ) {}
}

#[Route('/api/questions', methods: ['POST'])]
public function create(
    #[MapRequestPayload]
    CreateQuestion $input,
    QuestionService $questions,
): JsonResponse
{
    $question = $questions->create($input);
    return $this->json(['id' => $question->getId()], 201);
}

Невалідний JSON або порушені обмеження дають відповідь 422 зі списком помилок. Для query string є #[MapQueryString] і #[MapQueryParameter], для поточного користувача — #[CurrentUser].

Area → префікс і firewall

Symfony · config/routes.yaml

admin:
    resource: ../src/Controller/Admin/
    type: attribute
    prefix: /admin
    name_prefix: admin_

Доступ до /admin закривають у security.yaml (див. розділ про безпеку). Окремого DI-конфігу для area немає: якщо в адмінці потрібна інша реалізація сервісу, це два різні сервіси.