ThinkPHP 6+ 已彻底移除 Action 类,替代方案是继承 think\Controller 并采用 RESTful 风格:方法名对应 HTTP 动词(如 index、save)、需显式注册资源路由,且 save() 仅响应 POST、update() 仅响应 PUT/PATCH。

ThinkPHP 6+ 已彻底移除 Action 类,别再找继承它的方式
ThinkPHP 5.1 开始标记 Action 为废弃,6.0 直接删除。你如果还在查“如何继承 Action”或试图复用旧控制器模板,这条路已经不存在了——框架底层连类定义都没了。
替代方案不是“升级写法”,而是切换到基于 Controller 基类 + 请求方法映射的 RESTful 风格。核心变化是:不再靠类名后缀(如 IndexAction)识别控制器,而是靠路由绑定 + 方法命名约定。
-
app/controller/Index.php中定义Index类,继承think\Controller(TP6)或think\controller\Base(TP5.1) - 所有操作方法必须是
public,且不带任何后缀(不能叫indexAction()) - 方法名直接对应 HTTP 动词 + 资源名,例如
index()(GET 列表)、save()(POST 创建)、update()(PUT/PATCH 修改)
RESTful 路由必须显式注册,不能依赖默认行为
TP6 默认关闭自动 RESTful 解析。即使你写了 index()、save() 这些方法,不配路由,它们就是普通方法,不会按 HTTP 方法触发。
必须在 route/app.php 中用 Route::resource() 或手动绑定:
// 正确:声明资源路由
Route::resource('users', 'User');
// 错误:只写这一行,没启用 RESTful 映射
Route::get('users', 'User@index');
注意:Route::resource() 会自动绑定 7 种标准方法,但前提是你的控制器方法名严格匹配约定(index、read、save、update、delete、create、edit),且大小写一致。少一个、拼错一个,对应接口就 404。
save() 和 update() 的参数处理逻辑完全不同
这是最容易出错的地方:两个方法都接收数据,但框架对请求方式和参数来源的判断逻辑不同。
-
save()只响应POST请求,自动从$this->request->post()取值;若收到PUT或PATCH,哪怕方法存在也不会调用它 -
update()只响应PUT/PATCH,且默认要求 URL 中含主键(如/users/123),否则$id参数为空 - 如果你强行用
POST /users/123并希望走更新逻辑,得手动改路由或重写方法,不能指望框架自动识别
常见错误现象:save() 被调用但数据为空——其实是前端发了 PUT,而你没写 update(),也没配路由,结果进了空的 __call() 或报 404。
兼容旧项目时,别硬套 RESTful,优先用闭包路由过渡
如果老项目大量使用 xxxAction 命名、参数靠 GET 传 ID、操作混在同一个方法里,强行改成标准 RESTful 会引入大量路由冲突和逻辑拆分成本。
更务实的做法是:保留原有方法名(如 userList()、userEdit()),用闭包或显式路由绑定,绕过资源路由约束:
Route::get('user/list', function () {
return (new app\controller\User())->userList();
});
Route::post('user/edit', function () {
return (new app\controller\User())->userEdit();
});
这样既避开废弃的 Action 机制,又不用立刻重构业务逻辑。等接口稳定、前端适配完成,再逐步迁移到标准资源路由。
真正麻烦的不是写法替换,而是 URL 设计是否真符合资源语义。比如把“导出报表”塞进 export() 方法,再挂到 GET /reports/export 下,看起来 RESTful,实则违反幂等性——这种细节比继承哪个基类重要得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











