ThinkPHP6项目中更推荐使用zircote/swagger-php+v4.x(PHP≥8.0)或v3.4.1(PHP7.4)生成OpenAPI 3.0文档,需注意PHP版本匹配、注释位置紧贴方法、路径扫描范围、.json静态文件访问配置及UTF-8编码规范。

think-apidoc 不是 ThinkPHP6 官方维护的文档扩展,实际项目中更推荐用 zircote/swagger-php + swagger-ui 组合,它能生成标准 OpenAPI 3.0 文档,兼容性好、调试工具链成熟。
安装 swagger-php 扩展时 composer 报错或 vendor 下没生成文件
常见原因是未指定 PHP 版本约束,或已存在冲突的旧版注解库。ThinkPHP6 要求 PHP ≥ 7.2,而 zircote/swagger-php v4.x 要求 PHP ≥ 8.0,直接运行 composer require zircote/swagger-php 在 PHP 7.4 环境下会失败。
解决办法:
- 确认当前 PHP 版本:
php -v;若为 7.4,改用 v3.4.1(最后支持 PHP 7.4 的稳定版):composer require zircote/swagger-php:^3.4.1 - 如果项目已装过
doctrine/annotations且版本过高(如 2.x),需降级:composer require doctrine/annotations:^1.13 - 执行后检查
vendor/zircote/swagger-php是否存在,不存在说明安装中断,可加-vvv查看详细错误
控制器里写 OpenAPI 注释但生成文档为空
注释必须紧贴方法声明上方,且不能被其他代码(包括空行、use 语句、类注释)隔开。ThinkPHP6 默认不扫描 app 目录外的控制器,如果你把 API 放在 app/api/controller 下,要确保路径在扫描范围内。
立即学习“PHP免费学习笔记(深入)”;
实操要点:
- 注释块必须以
/**开头、*/结尾,中间每行以*开头,不能混用// - 必须包含
@OA\Get或@OA\Post等操作标签,仅@OA\Info不会触发接口识别 - 若使用多应用(如
api应用),需在生成命令中显式指定路径:php ./vendor/bin/openapi app/api/controller/ -o public/swagger.json -
@OA\Parameter中的in值必须是query、path、header或cookie,写成get或url会导致该参数被忽略
访问 /swagger.json 返回 404 或空白页
ThinkPHP6 默认不暴露 public 下的 JSON 文件,尤其当启用了路由完整匹配或设置了 url_html_suffix 时,/swagger.json 可能被当成控制器方法拦截。
快速验证和修复方式:
- 先用 CLI 生成一次:
php ./vendor/bin/openapi app/ -o public/swagger.json,然后直接通过http://localhost:8000/swagger.json访问,看是否返回 JSON 内容 - 如果返回 404,检查
public/.htaccess(Apache)或 Nginx 配置是否禁止了.json后缀的静态文件访问 - 如果返回空白但 HTTP 状态码是 200,大概率是 JSON 生成失败(比如注释语法错误),此时打开
app_debug => true,再请求一次,错误会输出到页面 - 不想暴露
swagger.json原始路径?可用路由绑定一个控制器方法,读取并输出文件内容,但注意加权限控制
中文注释乱码或字段描述不显示
Swagger-PHP 解析注释时默认按 UTF-8 处理,但 Windows 系统下某些编辑器(如老版 Notepad)保存的 PHP 文件可能是 GBK 编码,导致 @description 或 @summary 解析失败,字段名显示为 undefined。
检查与修正步骤:
- 用 VS Code 或 PhpStorm 打开控制器文件,右下角查看当前编码,如果不是
UTF-8 with BOM或UTF-8,点击切换并保存 - 确认注释中没有非法 Unicode 字符(如从 Word 复制的长破折号、全角空格),这类字符会导致整个注释块解析失败
-
@OA\Schema中的title和description必须是字符串字面量,不能调用函数或变量,例如description="用户列表"✅,description=Lang::get('user.list')❌ - 如果用了
@OA\Property描述返回字段,type值必须小写(string、integer、boolean),大写(String)会被忽略
真正卡住人的地方,往往不是“怎么装”,而是生成命令跑通了、JSON 也有了,但 Swagger UI 页面里死活看不到接口——八成是注释位置偏了半行,或者 @OA\Get 少了个反斜杠。建议第一次调试时,先复制官方最简示例粘过去,确认基础流程走通,再逐步替换为你自己的逻辑。



















