CodeIgniter 通过统一路由指向同一控制器方法(如 $route['api/user/(:num)'] = 'api/user/index/$1';),再在 index() 中用 $this->input->method(TRUE) 判断请求类型并分发至 _get()、_post() 等私有方法,同时兼容 _method=PUT 参数及 CLI 环境。

CodeIgniter 怎么让同一个 URL 支持 GET、POST、PUT、DELETE
CodeIgniter 本身不直接区分 HTTP 方法来路由,$route 数组只管 URI 匹配,不管请求方式。想让 /api/user/123 同时响应 GET(查)、POST(新建)、PUT(更新)、DELETE(删),得靠控制器内部判断,而不是靠路由配置。
常见错误是试图写多个 $route['api/user/(:num)'] = 'api/user/get/$1' 和 $route['api/user/(:num)'] = 'api/user/update/$1' —— 这会覆盖,最后只生效一个。
- 路由只需定义一次:
$route['api/user/(:num)'] = 'api/user/index/$1'; - 所有请求都打到
Api_user::index(),再在方法里用$this->input->method()判断类型 - CI3 默认不自动加载
input类,建议在控制器构造函数里显式$this->load->library('input');或确保已启用 autoload
在控制器里怎么安全分发不同请求
别手写一堆 if ($this->input->method() === 'get') { ... } 堆砌逻辑。容易漏掉 HEAD、PATCH,也难维护。
推荐结构化处理:
- 把各方法拆成私有方法:
_get($id)、_post()、_put($id)、_delete($id) - 在
index()中统一调度:switch ($this->input->method(TRUE)) { case 'GET': return $this->_get($id); ... } - 注意
$this->input->method(TRUE)返回大写字符串(如'PUT'),FALSE返回小写,建议用TRUE避免大小写陷阱 - 对非预期方法,显式返回 405:
show_404()或手动设状态码:$this->output->set_status_header(405);
RESTful 场景下要注意的兼容性坑
浏览器表单只能发 GET/POST;PUT/DELETE 需前端用 fetch 或 XMLHttpRequest 显式设置 method。但有些老代理或服务器会过滤非标 method,这时 CI 可能收不到真实 method。
- CI3 会尝试从
X-HTTP-Method-Override头读取真实意图(如果开启$config['allow_get_array'] = TRUE并配合中间件) - 更稳妥的做法:允许 POST 携带
_method=PUT参数(类似 Laravel),并在控制器开头做预处理:if ($this->input->post('_method')) { $_SERVER['REQUEST_METHOD'] = strtoupper($this->input->post('_method')); } - 注意:这种改写只影响当前请求生命周期,不影响后续
$this->input->method()的返回值,所以必须在调用前做
为什么不能靠 .htaccess 或 Nginx 重写来“转换”请求方式
有人想用 RewriteRule 把 PUT /user/123 重写成 POST /user/123?_method=PUT —— 这没用。Apache/Nginx 重写的是路径和查询参数,无法篡改原始 HTTP method。浏览器或客户端发出的 method 是 TCP 层就确定的,服务器只能读,不能“转”。
真正起作用的只有两处:前端发什么 method,后端代码怎么读它。其他都是障眼法。
最易被忽略的一点:CI3 的 $this->input->method() 在 CLI 模式下返回 'cli',不是 HTTP method;如果你的 API 同时支持 Web 和命令行调用,得先判断运行环境再决定是否走 method 分发逻辑。


















