PHP项目Symfony路由与注解

wen PHP项目 2

Symfony路由与注解详解

基础概念

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

PHP项目Symfony路由与注解

支持的注解格式:

# 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应用。

抱歉,评论功能暂时关闭!