Symfony路由与注解详解
基础概念
Symfony提供了多种路由配置方式,注解(Annotations)是最常用的一种。

支持的注解格式:
# YAML格式(传统方式)
# config/routes.yaml
blog_list:
path: /blog
controller: App\Controller\BlogController::list
# 注解格式(现代方式)
/**
* @Route("/blog", name="blog_list")
*/
public function list(): Response
注解路由基础
1 安装依赖
composer require annotations
2 基本注解
// src/Controller/BlogController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class BlogController extends AbstractController
{
/**
* @Route("/blog", name="blog_list")
*/
public function list(): Response
{
return $this->render('blog/list.html.twig');
}
}
路由参数
/**
* @Route("/blog/{page}",
* name="blog_paginated",
* requirements={"page": "\d+"},
* defaults={"page": 1},
* methods={"GET"}
* )
*/
public function paginatedList(int $page): Response
{
// $page 自动注入
return $this->json(['page' => $page]);
}
高级注解路由
1 前缀路由(类级别)
/**
* @Route("/api", name="api_", host="api.example.com")
*/
class ApiController extends AbstractController
{
/**
* @Route("/users/{id}", name="user_show")
*/
public function showUser(int $id): Response
{
// URL: /api/users/123
// Route name: api_user_show
}
}
2 条件路由
/**
* @Route("/product/{slug}",
* condition="context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
* )
*/
public function productDetails(string $slug): Response
{
// 仅在Firefox浏览器且GET/HEAD请求时匹配
}
PHP 8属性路由(新版)
Symfony 5.2+支持PHP 8原生属性:
use Symfony\Component\Routing\Annotation\Route;
class ProductController extends AbstractController
{
#[Route('/product/{id}', name: 'product_show', methods: ['GET'])]
public function show(int $id): Response
{
// ...
}
#[Route('/product/new', name: 'product_new')]
#[IsGranted('ROLE_ADMIN')]
public function new(): Response
{
// 多个属性组合
}
}
实用技巧
1 路由分组
/**
* @Route(
* path = {
* "en": "/en/about",
* "zh": "/zh/about"
* },
* name = "about_us"
* )
*/
public function about(): Response
{
// 多语言路由
}
2 资源路由
/**
* @Route("/resource")
*/
class ResourceController extends AbstractController
{
/**
* @Route("/", name="resource_index", methods={"GET"})
*/
public function index(): Response {}
/**
* @Route("/new", name="resource_new", methods={"GET","POST"})
*/
public function new(): Response {}
/**
* @Route("/{id}", name="resource_show", methods={"GET"})
*/
public function show(int $id): Response {}
/**
* @Route("/{id}/edit", name="resource_edit", methods={"GET","POST"})
*/
public function edit(int $id): Response {}
}
性能优化与调试
1 路由缓存
# 清除路由缓存 php bin/console cache:clear # 查看所有路由 php bin/console debug:router # 查看特定路由详情 php bin/console debug:router blog_list
2 路由懒加载
# config/routes.yaml
controllers:
resource: ../src/Controller/
type: annotation
lazy: true # 启用懒加载
常见问题与最佳实践
1 避免路由冲突
// 推荐:明确指定方法
/**
* @Route("/post/{id}", methods={"GET"}, name="post_show")
*/
public function show(Post $post): Response {}
/**
* @Route("/post/{id}", methods={"DELETE"}, name="post_delete")
*/
public function delete(Post $post): Response {}
2 参数验证
/**
* @Route("/user/{email}",
* requirements={"email": "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"},
* name="user_by_email"
* )
*/
public function userByEmail(string $email): Response
{
// 邮箱格式验证
}
3 路由命名规范
# 推荐命名模式
/**
* @Route("/admin/users/create", name="admin_users_create")
*/
# 前缀_控制器_动作
完整示例
#[Route('/admin', name: 'admin_')]
class AdminController extends AbstractController
{
public function __construct(
private UserRepository $userRepository
) {}
#[Route('/dashboard', name: 'dashboard')]
#[IsGranted('ROLE_ADMIN')]
public function dashboard(): Response
{
return $this->render('admin/dashboard.html.twig');
}
#[Route('/users/{page}',
name: 'users_list',
requirements: ['page' => '\d+'],
defaults: ['page' => 1]
)]
public function listUsers(int $page): Response
{
$users = $this->userRepository->findByPage($page);
return $this->json($users);
}
#[Route('/users/{id}/toggle-status',
name: 'user_toggle_status',
methods: ['POST']
)]
public function toggleUserStatus(int $id): Response
{
// 启用/禁用用户
}
}
调试工具
# 路由调试命令 php bin/console debug:router --show-controllers php bin/console router:match /product/123 php bin/console make:controller BlogController
最佳实践总结:
- ✅ 使用PHP 8属性注解(新项目)
- ✅ 为路由提供有意义的名称
- ✅ 明确指定HTTP方法
- ✅ 使用参数验证(requirements)
- ✅ 合理使用类级别前缀
- ❌ 避免过长的路由路径
- ❌ 不要在路由中硬编码参数
Symfony的路由系统提供了强大的灵活性和性能,合理运用这些特性可以构建出结构清晰、易于维护的Web应用。