Discuz! X5.0 RESTful 门户发文 /pub/article 接口实践

本文摘要背景Discuz! X5.0 原生 RESTful API 除了能操作论坛(发帖、回帖、版块),还支持门户(Portal)文章发布。在打通「认证 → 发帖」之后,进一步尝试把内容发布到门户 CMS,并在这个过程中定位到一个非常隐蔽的坑:highlight_style 参数必须以 PHP 数组形式提交,否则直接 503。本文记录 /pub/article 门户发文接口的调用方式、参数结构,以及 hi...

Discuz! X5.0 RESTful 门户发文接口与 highlight_style 数组坑

背景

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/viewportal/listportal/commentportal/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,并带上 titlecontentcatid
  • 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

觉得内容不错?我要

评论 暂无评论
暂无评论,快来抢沙发吧~