1

我们如何覆盖要显示的错误消息,针对单个验证规则多次显示。

我试图在下面的代码中做到这一点,但它显示了最后设置的错误消息,即'b'

我在这里尝试做的是,为“first_name”显示错误“a”,为 last_name 显示错误“b”。

<?php

/*
This program will test whether we could override the codeingiter error messages from the validation helper. 
We are going to use the 'set_message' function.
*/ 

class Message_override extends CI_Controller{

public function __construct(){

    parent::__construct();
    $this->load->helper('url');
}

public function index(){

    $this->load->view('message_override_view');
}

public function display_error(){

    $this->load->library('form_validation');

    $this->form_validation->set_message('numeric','a');
    $this->form_validation->set_rules('txt_first_name', 'First Name', 'numeric');

    $this->form_validation->set_message('numeric','b');
    $this->form_validation->set_rules('txt_last_name', 'Last Name', 'numeric');

    if($this->form_validation->run()==FALSE)
    {
        print_r(validation_errors());
    }
    else
    {
        echo '<pre>';
        print_r($_POST);
    }
  }
}

?>
4

1 回答 1

3

CodeIgniter 本身不支持同一规则的多个错误消息,但您可以尝试以下几种解决方法:

正如@HashemQolami 建议的那样,您可以使用多个回调函数并为每个回调函数设置不同的错误消息:

$this->form_validation->set_rules('txt_first_name', 'First Name', 'callback_numeric_a');
$this->form_validation->set_rules('txt_last_name', 'Last Name', 'callback_numeric_b');

这种方法的缺点是它显然不是模块化的,而是重复的,因为您需要在控制器中定义多个函数,比如这个

public function numeric_a($str){
    $this->form_validation->set_message('numeric_a', 'a');  
    return $this->numeric($str);
}

我使用的另一个解决方法是将规则的消息设置为%s语言文件中,然后将自定义消息设置为字段的标签

$lang['numeric'] = '%s';

$this->form_validation->set_rules('txt_first_name', 'a', 'numeric');
$this->form_validation->set_rules('txt_last_name', 'b', 'numeric');

这里的缺点是它基本上会弄乱错误消息系统,因为您必须为每个字段定义标签,并且每个字段只能使用一个验证规则才能正常工作。我仍然发现它在联系表单中很有用,您基本上只需要验证一些必填字段的存在。

现在,由于我发现自己需要更好地实现此功能,因此您的帖子启发了我对表单验证类进行了简单的扩展,不幸的是,execute由于没有用于检索的特殊功能,因此我不得不“破解” main 方法错误消息。

我添加了一种方法set_custom_message()来为特定字段或字段数组设置规则的自定义消息。

$this->form_validation->set_custom_message('txt_first_name','numeric','a');
$this->form_validation->set_custom_message('txt_last_name','numeric','b');
//Example passing an array of fields
$this->form_validation->set_custom_message(array('txt_first_name','txt_last_name'),'numeric','c');

这是扩展类的代码,以防其他人感兴趣:

请注意,这是基于CodeIgniter v2.1.4中包含的表单验证类

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * MY_Form_validation Class
 *
 * Extends Form_Validation library
 *
 * Adds custom message support.
 *
 */
class MY_Form_validation extends CI_Form_validation {

    protected $_custom_messages = array();

    public function set_custom_message($field = '', $rule = '', $message = '' ){
        if(is_array($field)){
            foreach($field as $id){
                $this->_custom_messages[$id][$rule] =  $message;
            }
            return;
        }
        $this->_custom_messages[$field][$rule] =  $message;
        return;
    }

    protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
    {
        // If the $_POST data is an array we will run a recursive call
        if (is_array($postdata))
        {
            foreach ($postdata as $key => $val)
            {
                $this->_execute($row, $rules, $val, $cycles);
                $cycles++;
            }

            return;
        }

        // --------------------------------------------------------------------

        // If the field is blank, but NOT required, no further tests are necessary
        $callback = FALSE;
        if ( ! in_array('required', $rules) AND is_null($postdata))
        {
            // Before we bail out, does the rule contain a callback?
            if (preg_match("/(callback_\w+(\[.*?\])?)/", implode(' ', $rules), $match))
            {
                $callback = TRUE;
                $rules = (array('1' => $match[1]));
            }
            else
            {
                return;
            }
        }

        // --------------------------------------------------------------------

        // Isset Test. Typically this rule will only apply to checkboxes.
        if (is_null($postdata) AND $callback == FALSE)
        {
            if (in_array('isset', $rules, TRUE) OR in_array('required', $rules))
            {
                // Set the message type
                $type = (in_array('required', $rules)) ? 'required' : 'isset';
                if(array_key_exists($row['field'],$this->_custom_messages) && 
                   array_key_exists($type,$this->_custom_messages[$row['field']])){
                       $line = $this->_custom_messages[$row['field']][$type];
                }else{
                    if ( ! isset($this->_error_messages[$type]))
                    {
                        if (FALSE === ($line = $this->CI->lang->line($type)))
                        {
                            $line = 'The field was not set';
                        }
                    }
                    else
                    {
                        $line = $this->_error_messages[$type];
                    }
                }

                // Build the error message
                $message = sprintf($line, $this->_translate_fieldname($row['label']));

                // Save the error message
                $this->_field_data[$row['field']]['error'] = $message;

                if ( ! isset($this->_error_array[$row['field']]))
                {
                    $this->_error_array[$row['field']] = $message;
                }
            }

            return;
        }

        // --------------------------------------------------------------------

        // Cycle through each rule and run it
        foreach ($rules As $rule)
        {
            $_in_array = FALSE;

            // We set the $postdata variable with the current data in our master array so that
            // each cycle of the loop is dealing with the processed data from the last cycle
            if ($row['is_array'] == TRUE AND is_array($this->_field_data[$row['field']]['postdata']))
            {
                // We shouldn't need this safety, but just in case there isn't an array index
                // associated with this cycle we'll bail out
                if ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))
                {
                    continue;
                }

                $postdata = $this->_field_data[$row['field']]['postdata'][$cycles];
                $_in_array = TRUE;
            }
            else
            {
                $postdata = $this->_field_data[$row['field']]['postdata'];
            }

            // --------------------------------------------------------------------

            // Is the rule a callback?
            $callback = FALSE;
            if (substr($rule, 0, 9) == 'callback_')
            {
                $rule = substr($rule, 9);
                $callback = TRUE;
            }

            // Strip the parameter (if exists) from the rule
            // Rules can contain a parameter: max_length[5]
            $param = FALSE;
            if (preg_match("/(.*?)\[(.*)\]/", $rule, $match))
            {
                $rule   = $match[1];
                $param  = $match[2];
            }

            // Call the function that corresponds to the rule
            if ($callback === TRUE)
            {
                if ( ! method_exists($this->CI, $rule))
                {
                    continue;
                }

                // Run the function and grab the result
                $result = $this->CI->$rule($postdata, $param);

                // Re-assign the result to the master data array
                if ($_in_array == TRUE)
                {
                    $this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result;
                }
                else
                {
                    $this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result;
                }

                // If the field isn't required and we just processed a callback we'll move on...
                if ( ! in_array('required', $rules, TRUE) AND $result !== FALSE)
                {
                    continue;
                }
            }
            else
            {
                if ( ! method_exists($this, $rule))
                {
                    // If our own wrapper function doesn't exist we see if a native PHP function does.
                    // Users can use any native PHP function call that has one param.
                    if (function_exists($rule))
                    {
                        $result = $rule($postdata);

                        if ($_in_array == TRUE)
                        {
                            $this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result;
                        }
                        else
                        {
                            $this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result;
                        }
                    }
                    else
                    {
                        log_message('debug', "Unable to find validation rule: ".$rule);
                    }

                    continue;
                }

                $result = $this->$rule($postdata, $param);

                if ($_in_array == TRUE)
                {
                    $this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result;
                }
                else
                {
                    $this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result;
                }
            }

            // Did the rule test negatively?  If so, grab the error.
            if ($result === FALSE)
            {
                if(array_key_exists($row['field'],$this->_custom_messages) && 
                   array_key_exists($rule,$this->_custom_messages[$row['field']])){
                       $line = $this->_custom_messages[$row['field']][$rule];
                }else{
                    if ( ! isset($this->_error_messages[$rule]))
                    {
                        if (FALSE === ($line = $this->CI->lang->line($rule)))
                        {
                            $line = 'Unable to access an error message corresponding to your field name.';
                        }
                    }
                    else
                    {
                        $line = $this->_error_messages[$rule];
                    }
                }

                // Is the parameter we are inserting into the error message the name
                // of another field?  If so we need to grab its "field label"
                if (isset($this->_field_data[$param]) AND isset($this->_field_data[$param]['label']))
                {
                    $param = $this->_translate_fieldname($this->_field_data[$param]['label']);
                }

                // Build the error message
                $message = sprintf($line, $this->_translate_fieldname($row['label']), $param);

                // Save the error message
                $this->_field_data[$row['field']]['error'] = $message;

                if ( ! isset($this->_error_array[$row['field']]))
                {
                    $this->_error_array[$row['field']] = $message;
                }

                return;
            }
        }
    }


// END MY Form Validation Class
/* End of file MY_Form_validation.php */
/* Location: ./application/libraries/MY_Form_validation.php */

}
于 2013-08-05T18:40:22.947 回答