CodeIgniter 4 表单验证必须显式调用 set_rules(),字段名需与 $_POST 键完全一致(大小写敏感),回调函数须为控制器 public 方法且命名严格匹配,失败后需手动使用 set_value() 和 validation_errors() 保留数据并显示错误。

验证规则必须显式 set_rules(),不能靠表单 name 自动推导
CodeIgniter 4 的 form_validation 类不会扫描 HTML 表单的 name 属性来自动建立规则。你必须在控制器里一条条写清楚字段名、提示名和规则串,否则验证就形同虚设。
常见错误是只写了 HTML 表单,却漏掉 $this->form_validation->set_rules(),结果 run() 总是返回 TRUE,后端直接接收空值或非法数据。
- 字段名(第一个参数)必须和
$_POST键完全一致,大小写敏感:比如表单里是<input name="Email">,规则就得写'Email',写成'email'就取不到值 - 第二个参数是纯文本标签,仅用于错误提示,不影响逻辑;但别留空,否则
validation_errors()可能输出 “The field is required” 这种无意义信息 - 规则串用竖线
|连接,顺序决定执行优先级:比如'required|min_length[6]|valid_email',一旦required失败,后面两个就不会检查 - 数组批量写法更安全:
$rules = [['field' => 'email', 'label' => '邮箱', 'rules' => 'required|valid_email']]; $this->form_validation->set_rules($rules);
callback_ 回调函数必须是控制器 public 方法,且签名严格固定
想查数据库判重、校验密码强度、或验证上传文件类型?只能靠回调函数。但它不是随便起个名就能用——命名、位置、参数、返回值全有硬约束。
典型错误是把回调写在模型里,或者方法名漏了 callback_ 前缀,结果 run() 静默跳过,连错误日志都不报。
- 方法必须定义在当前控制器内,且为
public;不能放在 helper 或 model 里 - 规则中写
'callback_check_email_exists',对应的方法名就得是check_email_exists(),少一个下划线或大小写错,就失效 - 参数只能有一个:
$str,就是该字段提交的原始值;不要在里面再调$this->request->getPost('email') - 失败时必须先调
$this->form_validation->set_message('check_email_exists', '邮箱已被注册'),再return FALSE;消息键名是去掉callback_后的部分
验证失败后,set_value() 和 validation_errors() 不是可选功能
很多人以为 run() === FALSE 后 reload view 就完事了,结果用户一提交失败,表单清空、错误也不显示——这不是验证没生效,是漏掉了两个关键补丁。
CI4 不会自动保留字段值或注入错误 HTML,这两步必须手动做,缺一不可。
- 在视图里所有输入框的
value属性里用set_value('email'),否则刷新后用户得重填全部内容 - 错误信息默认用
<p></p>包裹,直接插<?php echo validation_errors(); ?>即可;如需自定义样式,传参:validation_errors('<div class="alert">', '</div>') - 如果用了
form_open(),记得开启 CSRF:form_open('user/save', ['id' => 'myform'])会自动加隐藏域;没开的话,run()可能因 token 缺失直接失败
CI4.7.0 中 is_unique 规则仍可用,但要注意表名格式
is_unique[table_name.field_name] 是最常用的去重规则,但在 CI4.7.0 中,它依赖 Query Builder 的语法解析,表名不能带前缀或数据库名,否则会报 SQL 错误。
比如你的表实际叫 ci4_users,配置项里设置了前缀 $db['default']['prefix'] = 'ci4_';,那么规则里必须写 'is_unique[users.email]',而不是 'is_unique[ci4_users.email]'。
- 规则内部会自动拼上前缀,硬写全名会导致生成类似
WHERE `ci4_ci4_users`.`email` = ...的错误 SQL - 若用的是多数据库连接,
is_unique默认走default组,跨库校验需改写回调函数 - 该规则只查
NULL和空字符串以外的值,如果允许邮箱为空(非必填),又想保证“非空时唯一”,得组合写:'required|valid_email|is_unique[users.email]'


















