导读:本期聚焦于半夏创作的《CodeIgniter 3 中自定义表单验证规则库的正确实现方式》,敬请观看详情。如何在CodeIgniter 3中编写可复用的自定义表单验证规则类。很多项目的验证逻辑散落在各个控制器里,重复代码多且难以维护。本文从MY_Form_validation扩展类讲起,逐步实现一个完整的自定义验证规则库,包括注册回调方法、配置规则访问路径、错误提示信息的多语言处理,以及常用规则如手机号、身份证、密码强度等的具体写法,并指出回调方法写法与类方法写法的区别和常见报错的排查思路,让验证逻辑集中管理、随取随用。

为什么验证逻辑不应该散落在控制器里

CodeIgniter 3 自带的表单验证类(Form_validation)已经提供了 required、valid_email、min_length 等常用规则,但实际业务中总会遇到框架没有覆盖的场景:手机号归属地校验、身份证号码合法性、密码强度等级、用户名是否被占用等。如果这些逻辑都写在控制器的回调方法里,项目规模一旦扩大,同一条验证规则往往会在多个控制器中重复出现,修改一处规则就得全局搜索替换,维护成本非常高。

更好的做法是把所有自定义规则集中到一个继承自 CI_Form_validation 的扩展类中,这样验证规则可以在任何控制器里像内置规则一样直接引用,错误提示也统一由语言文件管理。CodeIgniter 3 提供了非常干净的扩展机制,只要遵循命名约定,框架会自动加载你的扩展类,完全不需要手动 include。

CodeIgniter 3 中自定义表单验证规则库的正确实现方式

创建 MY_Form_validation 扩展类的完整步骤

第一步是在 application/libraries 目录下新建文件 MY_Form_validation.php。注意类名前缀 MY 是由 application/config/config.php 中的 subclass_prefix 配置项决定的,默认就是 MY。类必须继承 CI_Form_validation,构造函数需要把配置参数透传给父类:

<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');

class MY_Form_validation extends CI_Form_validation {

    public function __construct($config = array())
    {
        parent::__construct($config);
    }

    /**
     * 验证中国大陆手机号
     */
    public function valid_phone($str)
    {
        if (preg_match('/^1[3-9]\d{9}$/', $str)) {
            return TRUE;
        }
        $this->set_message('valid_phone', '{field} 格式不正确');
        return FALSE;
    }

    /**
     * 验证身份证号码(18位,含校验位验证)
     */
    public function valid_idcard($str)
    {
        if (!preg_match('/^\d{17}[\dXx]$/', $str)) {
            $this->set_message('valid_idcard', '{field} 格式不正确');
            return FALSE;
        }
        $weights = array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);
        $codes   = array('1','0','X','9','8','7','6','5','4','3','2');
        $sum = 0;
        for ($i = 0; $i < 17; $i++) {
            $sum += (int)$str[$i] * $weights[$i];
        }
        if (strtoupper($str[17]) === $codes[$sum % 11]) {
            return TRUE;
        }
        $this->set_message('valid_idcard', '{field} 校验位不正确');
        return FALSE;
    }
}

扩展类就位后,框架在加载 form_validation 库时会自动识别并加载这个子类,不需要在 autoload.php 中做任何额外配置。如果确实想让它在全站自动可用,也可以把 form_validation 加入 autoload.php 的 libraries 数组,效果等同于自动加载扩展后的版本。

有一个细节容易被忽略:扩展类的文件名必须与类名完全一致(区分大小写),在 Linux 服务器上 MY_Form_validation.php 与 my_form_validation.php 会被视为不同文件,命名不一致会直接报找不到类的错误。

在控制器中像内置规则一样调用自定义规则

扩展类写好之后,使用方式与内置规则没有任何区别,直接在 set_rules 中引用方法名即可。下面是一个典型的注册表单验证示例:

public function register()
{
    $this->load->library('form_validation');

    $this->form_validation->set_rules('phone', '手机号', 'required|valid_phone');
    $this->form_validation->set_rules('idcard', '身份证号', 'required|valid_idcard');
    $this->form_validation->set_rules('password', '密码', 'required|min_length[8]');

    if ($this->form_validation->run() == FALSE) {
        $this->load->view('user/register');
    } else {
        // 验证通过,处理注册业务
    }
}

除了直接写在字符串规则里,CodeIgniter 3 还支持把规则集中写在配置文件中。在 application/config 下创建 form_validation.php,框架运行 run() 时会自动读取,控制器里的代码会进一步精简,非常适合规则较多的中大型项目:

$config = array(
    'signup' => array(
        array(
            'field' => 'phone',
            'label' => '手机号',
            'rules' => 'required|valid_phone|is_unique[users.phone]'
        ),
        array(
            'field' => 'idcard',
            'label' => '身份证号',
            'rules' => 'required|valid_idcard'
        )
    )
);

配置文件方式还支持分组,控制器调用 run('signup') 即可执行指定分组的规则集。这样同一个控制器里多个表单(注册、绑定手机、实名认证)各自维护独立的规则组,互不干扰,可读性比在控制器里堆砌 set_rules 调用要好得多。

回调方法与类方法的区别及常见错误排查

CodeIgniter 3 支持两种自定义验证方式:写在控制器里的 callback_ 前缀方法,以及写在扩展类中的普通方法。控制器回调的规则写法是 callback_check_username,而扩展类方法直接写方法名。两者最大的区别在于作用范围:回调方法只能在当前控制器使用,扩展类方法全局可用。新项目建议统一使用扩展类方式,旧代码里的回调方法可以在重构时逐步迁移。

排查自定义规则不生效的问题时,可以按以下几个方向检查。第一,确认方法是否返回了布尔值,验证方法必须显式返回 TRUE 或 FALSE,返回 0、1 或 null 都会导致判断异常。第二,确认错误信息是否通过 set_message 设置,如果方法返回 FALSE 但没有设置错误消息,页面只会显示默认的 Unable to access an error message 提示。第三,如果规则带有参数,例如 greater_than[18],方法签名必须接收第二个参数:

/**
 * 验证日期必须早于指定日期,用法:before_date[2006-01-01]
 */
public function before_date($str, $param)
{
    $time = strtotime($str);
    if ($time === FALSE) {
        $this->set_message('before_date', '{field} 不是有效的日期');
        return FALSE;
    }
    if ($time < strtotime($param)) {
        return TRUE;
    }
    $this->set_message('before_date', '{field} 必须早于 ' . $param);
    return FALSE;
}

关于错误提示的维护,更规范的做法是把提示文本放进语言文件。在 application/language/chinese 目录下建立 form_validation_lang.php,然后扩展类中通过 $this->CI->lang->line('valid_phone') 读取,set_message 中也可以直接传语言键名。这样项目需要支持多语言,或者产品经理要求统一修改文案时,只需要改语言文件一处即可,所有规则提示同步生效。

总结一下,把自定义验证规则沉淀到 MY_Form_validation 扩展类中,配合配置文件式规则分组和语言文件管理错误提示,是 CodeIgniter 3 项目中处理表单验证最稳妥的组织方式。它让验证逻辑具备可复用、可测试、可集中维护三个特性,项目越复杂,这种结构带来的收益就越明显。

CodeIgniter 3表单验证自定义规则库修改时间:2026-09-14 13:35:51

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260914/56716.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。