CI(codeigniter 2.0.2)-表单元素名称使用数组形式时存在的bug

CI框架中默认集成了表单验证的类,表单提交时提供的验证方式有:必填、长度、邮箱、ip、比较等一些常用的验证,但是默认表单元素比较验证(matches[form_item])在验证的表单元素名称使用数组形式时获取不到对应表单元素值进行比较。

首先我们来看一下默认的框架默认的表单验证类;
路径:libraries\Form_validation.php
找到matches方法,代码如下:
function matches($str, $field) {
        if (!isset($_POST[$field])) {
            return FALSE;
        }

        $field = $_POST[$field];

        return ($str !== $field) ? FALSE : TRUE;
    }

       分析一下,当表单元素名(name)以正常的形式(如:password、confirm_password,下面以确认密码为例)的情况下,验证规则如下
        array(
                'field' => 'password',
                'label' => 'Password',
                'rules' => 'trim|required|md5'
            ),
            array(
                'field' => 'confirm_password',
                'label' => 'Confirm Password',
                'rules' => 'trim|matches[password]'
            )

系统进行验证confirm_password时matches方法中第二个参数$field为"password",这个时 候$_POST[$field]<=>$_POST["password"],$_POST["password"]得到表单元素 password的值,可以正确的校验两个表单元素;若表单元素名称使用数组形式(如:model[password]、 model[confirm_password])时验证规则如下
array(
                'field' => 'model[password]',
                'label' => 'Password',
                'rules' => 'trim|required|md5'
            ),
            array(
                'field' => 'model[confirm_password]',
                'label' => 'Confirm Password',
                'rules' => 'trim|matches[model[password]]'
            )

        这个时候进行验证model[confirm_password]的时候matches方法中第二个参数$field 为"model[password]",这个时候$_POST[$field]<=& gt;$_POST["model[password]"],$_POST["model[password]"]是获取不到 model[confirm_password]值的,那么无论你输入两次密码相等也返回的是False。

       通过分析发现,我们可以对原来的form_validation进行修改,为了不破坏框架内核在应用类库中对原来的类进行扩展覆盖原有方法,在 aplication\libraries下创建MY_Form_validation.php进行扩展(开发规范请参考CI开发手册,这里不多说),代 码如下

class MY_Form_validation extends CI_Form_validation {

    //put your code here
    public function __construct($rules = array()) {
        parent::__construct($rules);
    }

    function matches($str, $field) {
        if (strpos($field,'[') !== FALSE) {
            $field_arr = explode('[', str_replace(']', '', $field));
            if (!isset($_POST[$field_arr[0]])) {
                return FALSE;
            }
            $field_val = $this->get_arr_field_val($field_arr, $_POST[$field_arr[0]]);
            return ($str !== $field_val) ? FALSE : TRUE;
        }

        if (!isset($_POST[$field])) {
            return FALSE;
        }

        $field = $_POST[$field];

        return ($str !== $field) ? FALSE : TRUE;
    }

    function get_arr_field_val($arr, $post_val) {
        for ($i = 0; $i < count($arr); $i++) {
            if (isset($arr[$i + 1])) {
                if (isset ($post_val[$arr[$i + 1]])) {
                    $post_val = $post_val[$arr[$i + 1]];
                }
            }
        }
        return $post_val;
    }

}