Routes
Route attributes
Start with fixed paths. Each attribute maps one URL path to one method, and the name makes the route easy to reference later:
namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class BlogController { #[Route("/", name: "app_home")] public function home(): Response { return new Response("Home"); } #[Route("/about", name: "app_about")] public function about(): Response { return new Response("About"); } }
The path /about matches only that exact address. Dynamic parts arrive in the next section.
Parameters {slug}
Placeholders make one method serve many addresses. The placeholder {slug} matches any single part of the path, and Symfony passes the matched text into the argument with the same name:
namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class PostController { #[Route("/post/{slug}", name: "app_post")] public function show(string $slug): Response { return new Response("Post: " . $slug); } }
A request for /post/hello-world calls show with the slug set to hello-world.
Requirements
Placeholders accept anything by default, including values your method cannot use. A requirement narrows the match with a regular expression, so only digits reach the method below:
namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class PostByIdController { #[Route("/post/{id}", name: "app_post_id", requirements: ["id" => "\d+"])] public function byId(int $id): Response { return new Response("Post id: " . $id); } }
Letters and dashes no longer match, and such addresses fall through to a 404.
Route names
Names never appear in the browser address bar. They label routes for redirects and templates, so renaming a path never breaks the code that points to it:
namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; class OldController extends AbstractController { public function old(): Response { return $this->redirectToRoute("app_home"); } }
Prefix names with app_ to avoid clashes with bundle routes.
Next: Controllers
Article author: Arthur Isaev