
背景
Discuz! X5.0 原生 RESTful API 除了能操作论坛(发帖、回帖、版块),还支持门户(Portal)文章发布。在打通「认证 → 发帖」之后,进一步尝试把内容发布到门户 CMS,并在这个过程中定位到一个非常隐蔽的坑:highlight_style 参数必须以 PHP 数组形式提交,否则直接 503。
本文记录 /pub/article 门户发文接口的调用方式、参数结构,以及 highlight_style 数组参数这个反直觉的坑的根因。
说明:Discuz! RESTful API 的认证方式(header 签名)与 script 单段格式问题已在另一篇《Discuz! X5.0 RESTful API 发帖打通》中讲过,本文聚焦门户发文接口本身。
过程
门户发文接口:/pub/article
Discuz! X5.0 官方接口定义里,portal 模块自带了 portal/view、portal/list、portal/comment、portal/blockitem,但没有门户文章的发布接口。要往门户 CMS 写文章,需要按官方格式扩展一个模块化接口。
由于官方已注册 portal 模块(同 baseuri+ver 下不允许再插入同名子接口),采用新的模块名前缀 pub 来挂载门户发文端点:/pub/article,内部 script 仍指向 portal(走门户发布逻辑)。
接口的结构与论坛发帖同构:
<item id="pub">
<item id="article">
<t>(模块描述)</t>
<get>...</get>
<post>...</post>
<usage>...</usage>
</item>
</item>post 参数(发布文章时需要提交):
| 参数 | 说明 |
|---|---|
articlesubmit | 固定 yes,表示提交发布 |
title | 文章标题(必填) |
content | 文章正文(HTML,必填) |
catid | 门户文章分类 ID(必填,如 1) |
summary | 摘要(可选) |
author | 作者(可选) |
from / fromurl | 来源与来源链接(可选) |
highlight_style | 高亮样式数组(关键坑,见下) |
formhash | 表单校验(按需) |
坑:highlight_style 必须用 PHP 数组提交
发布时发现接口返回 HTTP 503,响应体大致为:
{"ret":0,"data":{...null...}}第一反应是参数不对或服务端异常。逐层排查后发现,问题出在一个不起眼的高亮参数上。
根因:门户发文逻辑内部会对 highlight_style 做数组拼接处理,大致等价于:
implode( ',' , $highlight_style ); // 期望 $highlight_style 是数组而接口定义(get 块)里声明了这个参数占位符:
<get>...highlight_style={:highlight_style:}...</get>后端拿到这个参数后无条件对它执行 implode()。PHP 的 implode() 如果传入的不是数组,会直接抛 TypeError,进而表现为 HTTP 503 内部错误。
正是这个「无条件对参数做数组操作」的设计,导致参数的提交格式被锁死:必须是数组。
于是提交方式有两种写法,结果天差地别:
- ❌
highlight_style=b&highlight_style=B→ PHP 解析成字符串(后者或拼接为b,B)→implode()抛 TypeError → 503 - ✅
highlight_style[]=b&highlight_style[]=B→ PHP 解析成数组["b","B"]→ 正常拼接,高亮生效
也就是说,即使你有两个同名参数,如果没有 [] 后缀,PHP 也只会当成字符串按 & 规则解析,而不会自动聚合成数组。必须显式加 [] 让 PHP 知道这是数组参数。
验证
用正确写法(highlight_style[]=b&highlight_style[]=B)提交后,接口返回 ret:0,文章成功写入门户,并可在 portal.php?mod=view&aid=xxx 在线查看。文章标题正确应用了加粗高亮(font-weight:bold),说明 b 高亮确实生效,而不仅是"能发布"。
补充:为什么 503 而不是开发时就能发现
这类问题容易漏,是因为:
- 接口正常参数下功能可用,只有带上高亮参数才触发分支。
- 503 是服务端异常的统一返回,不直接告诉你"参数类型错了"。
highlight_style是可选参数,很多人会直接省略,从而永远踩不到这个分支。
总结
正确做法
- 通过 RESTful 扩展门户发文接口时,模块名前缀要避开官方已占用的模块名(如
portal),否则后台导入会报「接口已经存在」。 - 发布文章必须显式传
articlesubmit=yes,并带上title、content、catid。 highlight_style必须以 PHP 数组形式提交:highlight_style[]=b&highlight_style[]=B。普通同名多参数(无[])会被 PHP 当成字符串,触发服务端implode()的 TypeError → 503。- 遇到 503 且响应是
{"data": null}这类"看着像成功其实是异常"的结构时,优先怀疑某个参数的类型不符合服务端预期(数组 vs 字符串),尤其是接口里声明了{:占位符:}且后端会做数组操作的参数。
参考
- Discuz! X5.0 官方 RESTful 接口定义(在线源):
http://api.witframe.com/discuzrestful - Discuz! X5.0 官方源码:
https://github.com/DiscuzTeam/DiscuzX
觉得内容不错?我要