set_value() 仅在post请求且验证失败未重定向时有效,从$_post取值,不读session或数据库;get请求、重定向后或字段名含多维数组时均为空。

set_value 为什么总是空?
因为 set_value() 只在表单提交失败(即控制器未重定向)且当前请求是 POST 时才有效。它不读 session、不自动缓存、也不从数据库取值——只从 $this->input->post() 的原始输入中拿数据。
常见错误现象:set_value('username') 在刷新页面后为空,或首次 GET 访问时显示“undefined index”警告(实际是 PHP notice,但 CI 默认屏蔽,容易误以为正常)。
- 确保控制器里没在验证失败后调用
redirect()—— 一旦重定向,POST 数据就丢了,set_value()必然为空 - 不要在 GET 请求中依赖
set_value()回填,它对 GET 参数完全无感 - 如果用了
$this->form_validation->run() === FALSE,必须原样渲染视图,不能跳转
set_value 第二个参数的作用和陷阱
set_value('email', 'user@example.com') 的第二个参数是“默认值”,仅当 POST 中没有 email 字段(或字段为空字符串)时才生效。但它不会覆盖非空的脏输入——比如用户输了个错邮箱 foo@bar,验证失败后,set_value('email') 仍返回 foo@bar,而不是你写的默认值。
使用场景:适合做占位提示(如登录页“请输入邮箱”),但不能当 fallback 数据源用。
- 第二个参数在表单首次加载(GET)时生效,但一旦 POST 过一次,后续就由 POST 值主导
- 若字段名带数组语法(如
name="user[phone]"),set_value()不支持直接解析嵌套键,会返回空——得用set_value('user[phone]')字符串原样匹配 - CI 3.1.11+ 对多维字段支持仍有限,别指望
set_value('user[address][zip]')能工作
和 form_error() 配合时的典型断点
set_value() 和 form_error() 是一对搭档,但它们不共享逻辑:前者读输入,后者读验证类的 $error_array。两者都依赖同一个前提——验证流程没被跳过、没提前 exit、也没在失败后 redirect。
容易踩的坑:form_error('username') 显示了错误,但 set_value('username') 为空,大概率是控制器里写了类似 if ($this->form_validation->run()) { ... } else { redirect('login'); } —— 错误地把失败分支也重定向了。
- 验证失败时,必须让执行流落到
$this->load->view() - CI 的
form_error()不会触发set_value(),反之亦然;它们只是“碰巧”常一起出现 - 如果自定义了验证规则并用
$this->form_validation->set_message(),不影响set_value()行为
替代方案:什么时候不该用 set_value
当需要回填数据库已有值(比如编辑页)、或跨请求保持数据(如分步表单)、或处理 AJAX 提交时,set_value() 就不够用了。它本质是个“POST 快照工具”,不是状态管理机制。
性能上无负担,但语义上容易误导——名字像“设置值”,实际只是“取值+兜底”。真要持久化中间态,得靠 session、数据库临时表,或前端 localStorage。
- 编辑已有记录时,优先用
set_value('title', $post['title']),其中$post来自模型查询,而非依赖 POST - AJAX 提交失败后,前端应自己保留输入值,后端返回 JSON 错误,
set_value()完全不参与 - CI4 已废弃这套 Helper,改用独立表单库或原生 HTML + PHP 变量拼接,老项目升级时注意兼容断层
真正麻烦的不是怎么写 set_value(),而是搞清它到底“在哪一刻”有值、“凭什么”没值——边界比想象中窄。










