defaults参数必须与方法签名对齐,路径中可选段需加?且requirements须兼容空值,YAML中defaults和requirements为同级键。

defaults参数必须和方法签名对齐
路由里设了 defaults={"page": 1},控制器方法却写成 public function list($page),运行时会报错——PHP 不允许非可选参数接收 null(当默认值没被传入时,Symfony 实际传的是 null)。正确写法是让方法参数显式带默认值:public function list(int $page = 1)。类型声明(int)和默认值(= 1)必须同时存在,否则类型不匹配或参数缺失都会触发 500。
可选路径段要加 ?,且 requirements 要兼容空值
想让 /blog 和 /blog/2 都走同一个路由,不能只靠 defaults,还得配合路径语法:#[Route('/blog/{page?}', defaults: ['page' => 1], requirements: ['page' => '\d+'])] 这样写是错的——{page?} 允许 page 为空,但 requirements: ['page' => '\d+'] 却要求它必须是数字,冲突。要么去掉 requirements(不推荐),要么把正则改成允许空:requirements: ['page' => '\d*'],再确保方法签名是 public function list(?int $page = 1) 或 public function list(string $page = '1')。
locale 类型的默认值常被忽略顺序问题
多语言场景下用 /{_locale?},设 defaults: ['_locale' => 'en'] 很常见,但容易踩两个坑:一是这个路由必须放在所有不带 _locale 的泛匹配路由之前,否则 /{slug} 会先匹配掉 /about,导致 /en/about 反而进不去;二是 Twig 中生成链接时,{{ path('app_post_show', {slug: 'foo'}) }} 不会自动补 _locale,得显式传:{{ path('app_post_show', {_locale: app.request.locale, slug: 'foo'}) }},否则生成的是无语言前缀的 URL。
YAML 配置里 defaults 是顶层键,不是嵌套在 requirements 下
在 config/routes.yaml 中写路由时,defaults 和 requirements 是同级键,不是 requirements 的子项。错写成:
blog_list:
path: /blog/{page}
controller: App\Controller\BlogController::list
requirements:
page: '\d+'
defaults: { page: 1 }
会导致 defaults 被当成 requirements 的一个字段而被忽略。正确结构是:
blog_list:
path: /blog/{page}
controller: App\Controller\BlogController::list
requirements: { page: '\d+' }
defaults: { page: 1 }
另外注意:YAML 中数字默认被解析为 int,但如果你在 PHP 方法里用了 string $page,就得写 defaults: { page: '1' }(加引号)来强制字符串类型,否则类型不一致仍会报错。



















