最简路径是:定义路由→写控制器方法→返回json();例如route::get('goods/:id','index/goods'),控制器中public function goods($id){$data=['id'=>$id,'name'=>'测试商品','price'=>99.9];return json($data);}即可跑通。

ThinkPHP6 中如何快速写出一个可用的 API 接口
直接上手写接口,别绕弯子。最简路径是:定义路由 → 写控制器方法 → 返回 json()。不需要验证、不用中间件、不碰模型也能跑通。
比如要提供一个商品详情接口,接收 goods_id 参数并返回数据:
- 在
route/app.php里加一行:Route::get('goods/:id', 'Index/goods'); - 在
app/controller/Index.php中写方法:public function goods($id) { // 模拟查一条数据 $data = ['id' => $id, 'name' => '测试商品', 'price' => 99.9]; return json($data); } - 访问
http://localhost/api/goods/123就能拿到 JSON 响应
注意:默认返回的是 Content-Type: application/json,但如果你用 Postman 测试时看到乱码,大概率是没设响应头编码 —— 实际项目中建议在基类控制器里统一加 $this->response->header('Content-Type', 'application/json; charset=utf-8');。
为什么 input() 在 API 场景下容易出错
很多人习惯用 input('goods_id') 取参数,但在纯 API 请求(尤其是 JSON Body)里会失效。
- GET 请求走 URL 查询参数,
input('xxx')能取到 - POST 表单提交(
application/x-www-form-urlencoded),input('xxx')也能取到 - 但 POST JSON(
application/json)时,input()默认不解析原始 body,必须显式调用$this->request->param()或$this->request->post()配合parse_type配置 - 更稳妥的做法是:先判断请求类型,再取值
if ($this->request->isPost() && $this->request->header('content-type') === 'application/json') { $data = json_decode($this->request->getContent(), true); } else { $data = $this->request->param(); }
漏掉这步,前端发 JSON 过来,后端始终收不到参数,排查时容易卡在“明明传了却读不到”这种低级但耗时的问题上。
ThinkPHP6 的 json() 返回不是万能的
json() 看似简单,但它默认不做状态码控制、不处理异常结构、不兼容部分前端框架对空数组/布尔值的解析。
- 它底层调用的是 PHP
json_encode(),遇到资源句柄、闭包、不可序列化对象会静默失败,返回空字符串或null - 返回
bool类型(如json(false))时,前端可能解析为{}或报错,取决于 JS 环境 - 如果想统一格式(比如都带
code、msg、data字段),别直接 returnjson(...),封装一个基类方法更可控protected function success($data = null, $msg = 'ok', $code = 200) { return json(['code' => $code, 'msg' => $msg, 'data' => $data])->code($code); } - 特别注意:TP6 的
json()不自动设置 HTTP 状态码,return json(...)->code(400)才真正生效
很多接口上线后被前端吐槽“返回结构不一致”,根源常在这里 —— 开发时图快直接 json(),没考虑错误分支、空数据、类型边界。
API 版本控制别只靠目录硬编码
把 v1、v2 控制器分开放进 app/api/v1/ 和 app/api/v2/ 目录,看着清晰,但维护成本高、复用性差、升级时容易漏改路由。
- 推荐用路由分组 + 前缀 + 中间件组合:
Route::group('api/v1', function () { Route::resource('users', 'User'); })->middleware('check_api_version:v1'); Route::group('api/v2', function () { Route::resource('users', 'UserV2'); })->middleware('check_api_version:v2'); - 中间件里做版本校验,比如检查 header 是否含
X-API-Version,或从 URL 提取后做白名单比对 - 避免在每个控制器里写
if (version == 'v2') { ... },逻辑分散且难测试 - 如果真要用目录隔离(如老系统迁移过渡期),记得在
config/app.php中确认auto_multi_app为true,否则多应用模式不生效
版本控制最容易被忽略的点,不是怎么写,而是“怎么平滑下线旧版”—— 没有日志埋点、没监控调用量、没留降级开关,等某天删掉 v1 代码,才发现还有 3% 的 APP 用户卡在旧版本里调不到接口。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











