feat(seo): og:image size for front matter images; short titles and explicit descriptions for From Magento to Symfony
en/articles/magento-to-symfony/core/routing.md
+2
−1
Routing and controllers
In Symfony a route is an #[Route] attribute right on the controller method, with no routes.xml and no class per action. Action arguments such as entities, DTOs and services are filled in automatically.
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);
}
}
- The entity is resolved from the route parameter; if it doesn't exist, you get a 404 without writing any code. For
{id}you don't need the#[MapEntity]attribute. - You can request services directly in action arguments, not only in the constructor.
- URLs are generated by route name:
$this->generateUrl('faq_show', ['slug' => $q->getSlug()]). bin/console debug:routerlists all routes,router:match /faq/returnsshows which route will match.
JSON input: instead of getParam()
Symfony · DTO from the request body with validation
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);
}
Invalid JSON or violated constraints produce a 422 response with a list of errors. For the query string there are #[MapQueryString] and #[MapQueryParameter], for the current user there is #[CurrentUser].
Area → prefix and firewall
Symfony · config/routes.yaml
admin:
resource: ../src/Controller/Admin/
type: attribute
prefix: /admin
name_prefix: admin_
Access to /admin is restricted in security.yaml (see the security section). There is no separate DI config per area: if the admin panel needs a different implementation of a service, those are two different services.