CodeIgniter4中$request->getVar()收不到AJAX JSON数据,因getPost()/getGet()仅解析表单编码,JSON须用$request->getJSON(true);getVar()仅在Content-Type为application/json时才解析JSON体,否则回退POST/GET。

CodeIgniter4 的 $request->getVar() 为什么收不到 AJAX 提交的数据
常见现象是前端用 fetch 或 $.ajax 发送 JSON 数据(Content-Type: application/json),但后端 $this->request->getPost('key') 或 $this->request->getGet('key') 返回 null。
根本原因:CI4 的 getPost() 和 getGet() 只解析 application/x-www-form-urlencoded 或 multipart/form-data 请求体,不处理原始 JSON。
- 若前端发的是 JSON 字符串(如
{ "name": "Alice" }),必须用$request->getJSON(true)—— 第二个参数true表示自动将对象转为关联数组 - 若前端用
data: { name: "Alice" }(未设contentType),jQuery 默认发application/x-www-form-urlencoded,此时$request->getPost('name')才有效 - 混淆点:
$request->getVar('name')看似万能,但它按顺序检查 GET → POST → JSON → 路由段,仅当请求头是application/json且内容可解析时才读 JSON 部分;否则仍 fallback 到 POST/GET
控制器返回 JSON 时,setJSON() 和 echo json_encode() 的区别
CI4 推荐用 $this->response->setJSON($data),而不是手写 echo json_encode()。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
-
setJSON()自动设置响应头Content-Type: application/json,并调用json_encode(),还支持中文不转义(内部用JSON_UNESCAPED_UNICODE) - 手写
echo json_encode($data)必须手动加header('Content-Type: application/json'),否则前端dataType: 'json'会解析失败或触发 error 回调 - 若数据含非 UTF-8 字符(如 GBK 编码的旧数据库字段),
setJSON()会直接报错;而手写方式可加mb_convert_encoding()预处理,但需自行保证 header 正确
前端 AJAX 收到 404,但路由明明写了 quiz/get_item
CI4 默认 URL 是大小写敏感的,且控制器类名首字母大写、URL 路径必须全小写。
- 控制器文件名必须是
Quiz.php(首字母大写),类名也必须是class Quiz extends BaseController - 但访问路径必须是小写:
/quiz/get_item,写成/Quiz/get_item或/QUIZ/get_item都 404 - 确保
app/Config/Routes.php中没覆盖默认路由规则;如果用了$routes->add('quiz/get_item', 'Quiz::get_item'),也要确认方法get_item()是 public 且无参数(CI4 不允许带参数的静态路由直接映射) - 开发时可在控制器开头加
log_message('info', 'Route hit: ' . current_url());,看日志是否记录——没记录说明根本没进路由
CSRF 保护开启后,AJAX POST 总是 403
CI4 默认启用 CSRF,所有 POST/PUT/DELETE 请求必须携带有效 token,否则直接拒绝(不进控制器)。
- 前端必须从页面 HTML 中提取 token:
document.querySelector('meta[name="csrf-token"]').getAttribute('content'),或从 CI4 的csrf_token()辅助函数输出的隐藏字段中读取 - 发送请求时,需把 token 放在请求头或表单字段里:
headers: { 'X-CSRF-TOKEN': token }(推荐),或data: { ... , <code>csrf_test_name: token } - 注意:token 有有效期(默认 2 小时),页面长期未提交会导致失效;可刷新 token 后再发请求,但不要在每次 AJAX 前都重刷——除非你明确需要
- 调试时临时关闭 CSRF(仅限开发环境):
app/Config/Security.php中设public $csrfProtection = false;,但上线前务必改回true

















