Yii框架的路由怎么支持多种格式_json和xml格式路由后缀【解答】

2次阅读

yii2需配置urlmanager规则与contentnegotiator行为协同工作:启用enableprettyurl,添加通配符路由如’api/.{format}’,并在控制器中声明contentnegotiator行为映射application/json和application/xml到对应响应格式。

Yii框架的路由怎么支持多种格式_json和xml格式路由后缀【解答】

Yii2 中如何让路由自动识别 .json.xml 后缀

Yii2 默认不自动处理带 .json.xml 后缀的请求,必须显式配置 URL 解析规则和响应格式协商。核心不是“加后缀就能用”,而是让框架知道:这个后缀对应什么内容类型、该走哪个 action、返回时用什么序列化方式。

常见错误现象:404 Not Found(路由没匹配)、500UnsupportedMediaTypeHttpException)、或返回 HTML 而非 JSON/XML。

  • urlManager 配置中启用 enablePrettyUrlshowScriptName(否则后缀可能被 Web 服务器截断)
  • 添加带后缀的规则,例如 'api/users.<code>json‘ => ‘api/user/index’,但更推荐用通配符统一处理
  • 必须配合 ContentNegotiator 行为,否则即使 URL 匹配,Response 也不会自动设 Content-Type

怎么写一个能同时响应 .json.xml 的 action

别在每个 action 里手动判断后缀并 echo 字符串——那样破坏 Yii 的响应生命周期,也绕过异常处理和序列化逻辑。正确做法是:统一由 ContentNegotiator 拦截请求,再交由 Serializer 处理数据输出。

使用场景:restful API 接口,如 /v1/posts.json/v1/posts.xml 返回相同数据,仅格式不同。

  • 在 controller 类里声明 behaviors(),加入 ContentNegotiator,设置 formats 映射:['application/json' => Response::FORMAT_JSON, 'application/xml' => Response::FORMAT_XML]
  • 确保 Request 对象能从 URL 后缀推导出 Accept 头:需在 urlManager 中启用 useRequestParameters,或手动在 ContentNegotiatoracceptParam 设为 _format 并传参
  • Response::FORMAT_XML 要求数据是数组或实现了 toArray() 的对象;原生对象若无该方法会报错

.json.xml 路由后缀对性能和兼容性的影响

后缀本身不增加计算开销,但隐含两个实际成本:一是多一次正则匹配(URL 规则越多越明显),二是 XML 序列化比 JSON 慢且内存占用高,尤其数据量大时。

兼容性上,.xml 在现代前端调用中基本被弃用;部分代理或 CDN 可能缓存不同后缀为独立资源,导致 .json.xml 版本缓存不一致。

  • 避免在规则中写死多个重复路径,比如同时写 'posts.json''posts.xml';改用 'posts.<code>{format}‘ + defaults => ['format' => 'json']
  • XML 格式需注意特殊字符转义(如 &&),Yii 的 XmlResponseFormatter 会处理,但自定义 XML 构建容易遗漏
  • 如果只服务前端 JS,其实没必要支持 .xml;保留它只会增加测试和维护负担

为什么加了规则还是返回 404?检查这三处

最常卡在这几个地方,不是配置漏了,就是顺序或作用域错了。

  • urlManager 规则写在 rules 数组里,但放在了 hostInfobaseUrl 等非规则字段之后——YII 会忽略后续所有项
  • Web 服务器(如 nginx)把带点的路径当成静态文件,直接 404,没转发给 PHP;需确认 rewrite 规则是否覆盖 .json/.xml
  • controller ID 或 action ID 拼写错误,比如写了 user/index 却把 controller 命名为 UserController(正确)写成 UsersController(错误)

复杂点在于:URL 后缀、Accept 头、ContentNegotiator 的参数来源、Response 格式设置,这四者要对齐才真正生效。少一个环节,就只是“看起来配了,实际没走通”。

text=ZqhQzanResources