ThinkPHP6.x路由基础:优雅定义RESTful API接口
在ThinkPHP6.x构建RESTfulAPI时,使用Route::resource()仅保留必需动作,或手动注册路由避免隐式约定;通过分组配置API前缀;控制器方法名必须为index/read/save/update/delete,参数$id,继承think\Controller;显式调用json()返回JSON响应。
如果你在 ThinkPHP 6.x 中尝试构建标准的 RESTful API,却发现路由死活映射不到控制器方法、请求体取不到参数、或者返回格式总是不对劲——那八成是资源路由的定义与框架的约定没对齐。不必着急,下面这套步骤能帮你一次性搞定。
一、使用 Route::resource() 并显式限定动作
一句话声明就能生成语义清晰的 REST 路由,但别忘了排除掉 create 和 edit 这两个非 API 场景的动作,否则会暴露无意义的 HTML 表单路径,还可能引发路由冲突和扫描风险。
打开 app/route/app.php,在路由注册区域加上以下代码,然后用 only() 明确指定仅启用 API 必需的动作:
(此处演示代码省略,实际按项目结构写)
还要注意三点:控制器命名空间必须与路由声明一致——比如 Route::resource('users', 'api.User') 对应 app/controller/api/User.php 中的 User 类;控制器必须继承 think\Controller(不是 think\BaseController),否则资源方法调用会因为 __call() 拦截失效而报错 “method not exists”。
二、手动拆解注册精简 REST 路由
这个方法完全绕过 Route::resource() 默认的七动作绑定,用显式方式逐条定义 GET/POST/PUT/DELETE 路径。路径语义更纯粹,中间件可以自由附加,而且不依赖任何隐式约定。
具体做法:先删掉或注释掉所有 Route::resource() 调用,然后按标准 API 动作顺序注册。注意 PUT 和 PATCH 要共用同一方法,需要分别注册两条路由。每条路由都可以独立绑定中间件,比如统一加个 api 中间件用于鉴权与 JSON 响应封装。
三、配置 API 前缀并确保控制器解析正确
当需要版本化路径(如 /api/v1/users)时,如果直接把前缀写进资源路由字符串里,会导致控制器命名空间解析失败(比如误把 v1 当作应用名)。正确的做法是通过分组隔离前缀逻辑。
在 app/route/app.php 中用 Route::prefix() 包裹资源路由定义,并确保资源路由注册在 prefix 分组内部,而不是外部拼接路径字符串。同时验证控制器类是否位于 app/controller/api/User.php,类名和命名空间都要对得上。如果启用了多应用模式,检查 app/multi.php 中是否已声明 api 为合法应用名,否则 api.User 无法解析。
四、修正控制器方法签名与参数绑定
资源路由能不能正确分发请求,高度依赖控制器方法名、参数名及类型提示是否与框架内建规则严格匹配——任何一个偏差都可能导致 404 或参数为空。
- 方法名必须是 ThinkPHP 约定的七个之一:
index、read、save、update、delete(严禁使用show、store、destroy这种 Laravel 风格命名)。 read($id)和delete($id)的参数名必须为$id;想加类型安全可以写成read(int $id),否则路由无法完成参数绑定。update(Request $request, $id)必须把Request对象作为第一个参数,否则 PUT/PATCH 请求体内容拿不到。只写update($id)的话,$this->request->param()永远是空的。save()是唯一不带 ID 参数的方法,而且框架不会自动调用input()或param(),必须手动取参:$this->request->post()(表单)或$this->request->param()(JSON)。
五、强制 JSON 响应并规避常见格式陷阱
ThinkPHP 默认响应类型是 HTML,就算请求来自 AJAX 或者带了 application/json 头,如果不显式干预,返回值可能会被模板引擎渲染或者输出成未格式化的数组,前端解析直接翻车。
- 每个控制器方法末尾必须显式调用
json()并传入结构化数据。 - 禁用视图渲染:在控制器构造函数中设置
$this->view = null;,或者直接继承think\Controller(它的构造函数已经内置了这步操作)。 - 当
app_debug = false时,如果没配置default_ajax_return,JSON 请求会被静默丢弃——务必在config/app.php中加入相关设置。 - ThinkPHP 6+ 默认会对字符串参数执行
trim(),如果业务需要保留首尾空格字段,应该在验证器或中间件中关闭这个行为,否则input('content')会丢失原始空白字符。

核心要点就是这五步,逐一检查对位,你的 RESTful API 就能跑得顺顺畅畅。记住那句口诀:Route::resource() 声明位置、控制器命名空间、方法名(index/read/save/update/delete)、参数名($id)、继承 think\Controller、手动取参、显式 json() 响应——缺一不可,否则就是 404 或参数为空。
