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

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

Ashterix

docs(articles): From Magento to Symfony, a requalification guide grouped into sections

uk/articles/magento-to-symfony/core/routing.md новий файл +103 −0

1 + # Роутинг і контролери
2 +
3 + **Magento** · routes.xml + Controller/Question/View.php
4 +
5 + ```xml
6 + <router id="standard">
7 + <route id="faq" frontName="faq">
8 + <module name="Vendor_Faq"/>
9 + </route>
10 + </router>
11 + ```
12 + ```php
13 + class View implements HttpGetActionInterface
14 + {
15 + public function __construct(
16 + private RequestInterface $request,
17 + private QuestionRepositoryInterface $questions,
18 + private PageFactory $pageFactory,
19 + ) {}
20 +
21 + public function execute(): ResultInterface
22 + {
23 + $id = (int) $this->request->getParam('id');
24 + $question = $this->questions->getById($id);
25 + $page = $this->pageFactory->create();
26 + $page->getConfig()->getTitle()->set($question->getTitle());
27 + return $page;
28 + }
29 + }
30 + ```
31 +
32 + **Symfony** · src/Controller/FaqController.php
33 +
34 + ```php
35 + use Symfony\Bridge\Doctrine\Attribute\MapEntity;
36 + use Symfony\Component\Routing\Attribute\Route;
37 +
38 + final class FaqController extends AbstractController
39 + {
40 + #[Route('/faq', name: 'faq_index', methods: ['GET'])]
41 + public function index(QuestionRepository $questions): Response
42 + {
43 + return $this->json($questions->findActive());
44 + }
45 +
46 + #[Route('/faq/{slug}', name: 'faq_show', methods: ['GET'])]
47 + public function show(
48 + #[MapEntity(mapping: ['slug' => 'slug'])]
49 + Question $question,
50 + ): Response
51 + {
52 + return $this->json($question);
53 + }
54 + }
55 + ```
56 +
57 + - Сутність підставляється за параметром маршруту; якщо її немає, буде 404 без жодного коду. Для `{id}` атрибут `#[MapEntity]` не потрібен.
58 + - Сервіси можна просити прямо в аргументах дії, а не лише в конструкторі.
59 + - URL генерують за іменем маршруту: `$this->generateUrl('faq_show', ['slug' => $q->getSlug()])`.
60 + - `bin/console debug:router` — усі маршрути, `router:match /faq/returns` — який маршрут спрацює.
61 +
62 + ## JSON на вході: замість getParam()
63 +
64 + **Symfony** · DTO з тіла запиту з валідацією
65 +
66 + ```php
67 + final class CreateQuestion
68 + {
69 + public function __construct(
70 + #[Assert\NotBlank, Assert\Length(max: 255)]
71 + public readonly string $title,
72 + #[Assert\NotBlank]
73 + public readonly string $answer,
74 + ) {}
75 + }
76 +
77 + #[Route('/api/questions', methods: ['POST'])]
78 + public function create(
79 + #[MapRequestPayload]
80 + CreateQuestion $input,
81 + QuestionService $questions,
82 + ): JsonResponse
83 + {
84 + $question = $questions->create($input);
85 + return $this->json(['id' => $question->getId()], 201);
86 + }
87 + ```
88 +
89 + Невалідний JSON або порушені обмеження дають відповідь 422 зі списком помилок. Для query string є `#[MapQueryString]` і `#[MapQueryParameter]`, для поточного користувача — `#[CurrentUser]`.
90 +
91 + ## Area → префікс і firewall
92 +
93 + **Symfony** · config/routes.yaml
94 +
95 + ```yaml
96 + admin:
97 + resource: ../src/Controller/Admin/
98 + type: attribute
99 + prefix: /admin
100 + name_prefix: admin_
101 + ```
102 +
103 + Доступ до `/admin` закривають у `security.yaml` (див. розділ про безпеку). Окремого DI-конфігу для area немає: якщо в адмінці потрібна інша реалізація сервісу, це два різні сервіси.