直接用ResourceController(CI4)或RestController(CI3+restserver)可快速实现标准REST接口,无需手写路由、解析HTTP方法或设Content-Type;关键在于选对基类、配对路由、统一验证入口。

直接用 ResourceController(CI4)或 RestController(CI3 + restserver 库)就能跑通标准 REST 接口,不用手写路由映射、不用手动解析 HTTP 方法、也不用反复设 Content-Type。关键不是“能不能做”,而是选对基类、配对路由、管住验证入口。
CI4 中用 ResourceController 快速搭出 /api/users 资源
CI4 自带 ResourceController,它把 CRUD 映射到固定方法名,省去一堆 if ($this->request->getMethod() === 'PUT') 判断。
-
$routes->resource('users', ['controller' => 'Users'])这一行就注册了 7 个标准路由(GET /users、GET /users/123、POST /users等),不需要逐条写$routes->post() - 控制器必须继承
CodeIgniter\RESTful\ResourceController,且方法名严格为index()、show($id)、create()、update($id)、delete($id) -
$this->format = 'json'必须显式设置,否则默认返回 HTML;不设$modelName就得自己查 Model,设了会自动注入并绑定$this->model - 请求体是 JSON 时,
$this->request->getJSON()才能正确读取;若前端发的是application/x-www-form-urlencoded,得用$this->request->getPost(),别混用
CI3 用 philsturgeon/restserver 库支持 PUT/DELETE
原生 CI3 不解析 PUT 或 DELETE 的请求体,$_PUT 和 $_DELETE 是空的——这是最常卡住的地方。
- 必须用
require APPPATH.'libraries/REST_Controller.php'加载第三方库,不能只靠原生CI_Controller - 控制器继承
REST_Controller后,$this->put()、$this->delete()才有效;它们内部会从php://input解析原始数据 - 路由必须显式声明,比如
$route['api/users/(:num)']['put'] = 'api/users/update/$1',光写$route['api/users/(:num)'] = '...'不生效 - 如果前端发的是 JSON,
$this->put()返回的是关联数组;如果是表单数据,它返回的是普通 POST 键值对——别假设结构一致
验证失败时返回 400 而不是 500
很多接口在验证不通过时直接 echo json_encode(['error' => ...]) 并 exit,这会让前端无法区分是客户端错还是服务端崩了。
- CI4 用
$this->failValidationError($errors),自动返回400 Bad Request和标准化结构 - CI3 + restserver 用
$this->response(['error' => $this->form_validation->error_array()], 400),别漏掉第二个参数400 - 验证规则里慎用
required对可选字段:比如 PATCH 更新只传部分字段,required会导致整个请求被拒,该用permit_empty配合条件验证 - 不要在
create()或update()里手动调$this->model->insert()后才验证——验证必须在操作前完成,否则可能写入脏数据再回滚
GET 请求传复杂参数容易被截断或编码错误
URL 长度有限制,含数组、嵌套对象、长文本的 GET 参数极易被 Nginx/Apache 截断,或因 URL 编码不一致导致后端解析失败。
- 避免 GET 传大量过滤条件,改用
POST /api/users/search+ JSON body,用ResourceController的search_post()方法承接 - 必须用 GET 时,用
$this->request->getGet('q')(CI4)或$this->get('q')(restserver),别碰$_GET——它没经过 CI 的 XSS 过滤 - 前端传数组如
?status[]=active&status[]=pending,CI4 默认只取第一个status值;需用$this->request->getGet('status', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY) - 中文或特殊字符做 GET 参数时,前端必须
encodeURIComponent(),后端无需额外解码——CI 框架已自动处理
真正难的不是写出能跑的接口,而是让每个 HTTP 状态码都有明确语义、每种输入格式都被统一处理、每次错误都带可定位的上下文。这些细节不写进代码里,就只能靠日志和抓包来回推。


















