CodeIgniter自定义表单验证应优先使用控制器内public的callback_前缀回调函数,接收$str参数,返回严格布尔值,失败时先set_message再return FALSE,且须通过$this->访问模型/DB。

CodeIgniter 的自定义表单验证规则,绝大多数场景下应该用回调函数(callback_ 前缀方法),而不是试图去扩展核心类或写独立的验证类——后者容易破坏框架生命周期、引发 set_message 失效或 run() 返回假阳性。
回调函数必须定义在控制器里,且命名带 callback_ 前缀
这是硬性约定,不是可选项。Form_validation 类在解析规则字符串(如 'required|callback_check_email')时,会直接拼接方法名并用 method_exists() 检查是否存在。如果写成普通函数、放在模型里、或漏掉前缀,run() 会静默跳过该规则,不报错也不提示,最终导致验证“看起来通过了”但逻辑没执行。
-
callback_后面的名称必须和set_rules()中写的完全一致(大小写敏感) - 方法必须是
public,且接收一个参数:待验证字段的原始值($str) - 返回
TRUE表示通过;返回FALSE表示失败,并触发错误消息显示 - 不要在回调里调用
redirect()或exit(),验证阶段只负责判断
回调里访问数据库或模型时,必须用 $this-> 显式调用
常见错误是直接 new Model 或用全局函数查库,结果在 CLI 环境或某些路由模式下报 Call to a member function on null。CodeIgniter 的依赖注入是基于控制器实例的,所有资源($this->db、$this->user_model)都需通过 $this-> 获取。
- 正确写法:
$this->db->where('email', $str)->from('users')->count_all_results() > 0 - 错误写法:
new User_model()或get_instance()->db->...(虽能运行但绕过 CI 生命周期) - 若需复用逻辑,把查询封装进模型方法,再在回调里
$this->user_model->exists($str) - 注意:回调函数内不能使用
$this->input->post()重取值——$str就是当前字段已过滤后的值
set_message() 必须在回调返回 FALSE 前调用
很多人把 set_message() 放在回调开头或外面,结果错误消息不显示。Form_validation 只在规则返回 FALSE 且对应 message 已注册时才渲染提示。顺序错了,validation_errors() 就为空。
- 必须写成:
$this->form_validation->set_message('check_email', '邮箱已被注册');→return FALSE; - 消息键名(第一个参数)要和规则名中
callback_后的部分完全一致(这里是check_email,不是callback_check_email) - 支持占位符:
{field}替换为字段 label(如'Email'),{value}是实际值 - 避免在多个回调里重复调用
set_message()同一 key——后一次会覆盖前一次
复杂条件验证别硬塞进单个回调,拆成独立规则更可控
比如“密码和确认密码一致”+“密码强度达标”+“用户名未被占用”,如果全塞进一个 callback_validate_all(),调试困难、复用性差、错误消息无法分字段定位。CodeIgniter 允许同一字段绑定多个规则,也支持跨字段依赖。
- 用
matches[password]规则做前后端一致性校验,比手写回调更轻量 - 密码强度单独写
callback_password_strength($str),专注单一职责 - 跨字段逻辑(如“手机号非空时需校验格式”)可用
callback_phone_required_if_mobile(),并在回调里用$this->input->post('mobile')判断条件 - 注意:多个回调按规则字符串从左到右顺序执行,前面失败则后续不执行
最易被忽略的是回调函数的返回值类型——必须严格返回布尔值 TRUE 或 FALSE,任何其他返回(null、空字符串、整数 1)都会让 Form_validation 认为规则“未定义”,直接跳过,且不报任何警告。

















