Symfony 4:如何在控制器中获取services.yaml参数并用于注解
如何在Symfony控制器中共享并使用services.yaml定义的路由前缀参数
我来帮你搞定这个问题!在Symfony里要实现共享路由前缀并在控制器注解里复用,有几个非常实用的方案,我一个个给你讲清楚:
方案1:基础控制器继承(最省心的复用方式)
这是我最推荐的方案,一次性配置所有API控制器的前缀,后续新增控制器只要继承基础类就行。
首先在services.yaml里定义你的路由前缀参数:
# config/services.yaml parameters: app.route_prefix: '/api/v1'
然后创建一个基础API控制器,在类注解里用上这个参数:
// src/Controller/BaseApiController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; /** * @Route("%app.route_prefix%") */ class BaseApiController extends AbstractController { // 这里不需要写任何业务方法,纯作为父类提供路由前缀 }
接下来你的所有API控制器都继承这个基础类,方法注解里只需要写具体的路由路径就行:
// src/Controller/UserController.php namespace App\Controller; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Response; class UserController extends BaseApiController { /** * @Route("/users", name="api_users_list") * 实际路由:/api/v1/users */ public function list(): Response { return $this->json(['message' => '用户列表']); } /** * @Route("/users/{id}", name="api_users_show") * 实际路由:/api/v1/users/{id} */ public function show(int $id): Response { return $this->json(['用户ID' => $id]); } }
方案2:直接在注解中使用参数(灵活适配单个控制器)
如果不想用基础类,也可以直接在单个控制器的类注解或者方法注解里直接引用参数:
比如给某个控制器单独加前缀:
// src/Controller/ProductController.php namespace App\Controller; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Response; /** * @Route("%app.route_prefix%/products") * 实际基础路由:/api/v1/products */ class ProductController extends AbstractController { /** * @Route("", name="api_products_list") * 实际路由:/api/v1/products */ public function list(): Response { return $this->json(['message' => '商品列表']); } /** * @Route("/{id}", name="api_products_show") * 实际路由:/api/v1/products/{id} */ public function show(int $id): Response { return $this->json(['商品ID' => $id]); } }
甚至可以直接在方法注解里单独使用:
/** * @Route("%app.route_prefix%/orders/{id}", name="api_orders_show") */ public function showOrder(int $id): Response { return $this->json(['订单ID' => $id]); }
方案3:参数注入到控制器(动态获取前缀值)
如果需要在控制器的业务逻辑里动态使用这个前缀(比如返回的响应里要显示前缀),可以通过构造函数把参数注入进来:
// src/Controller/ApiInfoController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Response; class ApiInfoController extends AbstractController { private string $routePrefix; // 构造函数注入参数,参数名要和services.yaml里的参数名对应(驼峰转下划线) public function __construct(string $appRoutePrefix) { $this->routePrefix = $appRoutePrefix; } /** * @Route("%app.route_prefix%/info", name="api_info") */ public function getInfo(): Response { return $this->json([ 'api_prefix' => $this->routePrefix, 'status' => '正常' ]); } }
Symfony 4+版本会自动识别参数名并注入,如果你担心不生效,也可以在services.yaml里显式配置:
# config/services.yaml services: App\Controller\ApiInfoController: arguments: $appRoutePrefix: '%app.route_prefix%'
额外小技巧:YAML路由文件里也能用参数
如果你习惯用YAML写路由,同样可以复用这个参数:
# config/routes.yaml api_users_list: path: '%app.route_prefix%/users' controller: App\Controller\UserController::list
内容的提问来源于stack exchange,提问作者LuisF
相关产品推荐
相关产品推荐

