CodeIgniter - 验证空值

时间:2014-07-18 16:22:16

标签: php codeigniter

如何让CodeIgniter在拥有required规则但用户留空的字段上运行自定义规则?

我能想到的最好的方法是在字符串为空的情况下为字段添加空格,然后添加trim规则 - 但这会让人感到烦恼。

示例规则#1

仅当另一个字段具有特定值时才需要字段:

// depends[another_field.some_val]
public function depends($str, $field){
    list($post_key, $post_val)=explode('.', $field);
    if($_POST[$post_key] == $post_val){
        return $str != "";
    }
    return true;
}

示例规则#2

只有在数据库中存在正则表达式时才需要字段:

// regex[table_name.col_name.some_val]
public function regex($str, $field){
  list($table, $col, $post_val)=explode('.', $field);
  // Grab the regex
  $regex = $this->CI  ->db
                      ->limit(1)
                      ->select($col)
                      ->where($post_val, $_POST[$post_val])
                      ->get($table)
                      ->row($col);

  return preg_match('/'.$regex.'/', $str) === 1;
}

7 个答案:

答案 0 :(得分:1)

为什么对于简单的任务需要不同的功能。使用 if..else

假设 input1 的值等于 value1 ,则只需设置 required < / strong>另一个输入的验证规则,例如 input2

查看:

<form action="/controller_name/function_name/" method="POST">

    <input type="text" name="input1" />
    <input type="text" name="input2" />

    <input type="submit" />
</form>


控制器:

class Controller_name extends CI_Controller
{
    public function __construct()
    {
       parent::__construct();
       $this->load->library('form_validation');
    }

    public function function_name()
    {
        if($this->input->is_post())
        {
            if($this->input->post('input1') == 'value1')
            {
               $this->form_validation->set_rules('input2', 'input2', 'required');
            }

            if ($this->form_validation->run() == FALSE)
            {
                 // something's wrong in form!
            }
            else
            {
                 // form is good, proceed!
            }
        }
    }
}

答案 1 :(得分:1)

从代码中,您指出的问题是您需要创建一个字段。好吧,使用新规则创建一个必需的字段:'keep_checking'。这样,您强制系统检查您想要的任何内容。我做了什么:

  • 扩展系统核心类的My_Form_validation类(因此,您不必触及系统文件)。注意:不要忘记此文件位于application/libraries文件夹
  • 检查是否设置了自定义规则“keep_checking”。当设置'required'规则时,这将覆盖不检查字段的行为(参见下面的代码)

最后一点,在扩展Form_validation类之后,您将有一个位置可以放置您将一直使用的所有新自定义规则,XD

class MY_Form_validation extends CI_Form_validation
{
    public function __construct( $rules = array( ) ) {
        parent::__construct( $rules );
    }

    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;

        //====================================================================
        // NEW ADDED RULE > 'keep_checking', will check all the rules even if 
        // the field is empty
        //====================================================================
        if ( ! in_array('required', $rules) AND is_null($postdata) AND ! in_array( 'keep_checking', $rules ) )
        {
            // 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.
        //====================================================================
        // NEW ADDED RULE > 'keep_checking', will check all the rules even if 
        // the field is empty
        //====================================================================
    if (is_null($postdata) AND $callback == FALSE && !in_array( 'keep_checking', $rules ))
        {
            if (in_array('isset', $rules, TRUE) OR in_array('required', $rules))
            {
                // Set the message type
                $type = (in_array('required', $rules)) ? 'required' : 'isset';

                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 ( ! 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;
            }
        }
    }
}

更新:

Checkbox行避免继续检查。只需添加我添加的新行,它就可以了。您必须将keep_checking规则添加到要检查的任何字段:

class Welcome extends CI_Controller {

    /**
     * Index Page for this controller.
     *
     * Maps to the following URL
     *      http://example.com/index.php/welcome
     *  - or -
     *      http://example.com/index.php/welcome/index
     *  - or -
     * Since this controller is set as the default controller in
     * config/routes.php, it's displayed at http://example.com/
     *
     * So any other public methods not prefixed with an underscore will
     * map to /index.php/welcome/<method_name>
     * @see http://codeigniter.com/user_guide/general/urls.html
     */
    public function index()
    {
        $this->load->view('welcome_message');
    }

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

        $this->form_validation->set_rules('name',       'Name',     'keep_checking|required');
        $this->form_validation->set_rules('surname',    'Surname',  'keep_checking|is_numeric');

        if ( $this->form_validation->run() ) {

        } else {
            $this->load->view('form');
        }
    }
}

查看:form.php

<form action="test" method="post">

    <?php echo validation_errors(); ?>

    <p>
        Name: <input name="name">
    </p>
    <p>
        Surname: <input name="surname">
    </p>
    <p>
        <input type="submit" value="Send">
    </p>
</form>

提交该表单后,您将看到CI检查输入字段中的所有规则。最后一点,不要忘记MY_Form_validation进入库文件夹

Result of the checking

答案 2 :(得分:1)

在我的更新方法中,我只想提交脏的字段。如果一个不需要验证的字段被发送为空,则并非所有字段都是必需的并且验证失败。

因此,如果用户想要移除他们的手机,它会像 phone:"" 一样发送,如果我尝试像这样传递它,验证将不会看到它。

if($this-put("phone")) $this->form_validation->set_rules('phone', 'Phone', 'trim');

所以我不得不使用 array_key_exist() 来查看并传递它,即使它是空的。

if($this->put("description")) $this->form_validation->set_rules('description', 'Description', 'trim|required');

if(array_key_exists("phone", $this->input->post())) $this->form_validation->set_rules('phone', 'Phone', 'trim');

答案 3 :(得分:0)

我认为你要找的是callbacks

您可以在规则中定义回调

$this->form_validation->set_rules('field1', 'Field 1', 'trim|callback_field1_check');
$this->form_validation->set_rules('field2', 'Field 2', 'callback_field2_check');

现在你可以拥有一个带布尔返回值的函数。

public function field1_check($input) {
    if ($input != '') {
        $this->field1Set = true;
    }
}

public function field2_check($input) {
    // do something on $input
    $input = trim($input);
    // awesome thing is, you get to access all the field variables of your control here
    // so in some other function, you'll toggle a boolean to note that an optional field was filled
    // that variable set by other validation callback, you can use here
    if ($this->field1Set === true && $input == '') return false;
    return true;
}

答案 4 :(得分:0)

我已经通过编辑system/libraries/Form_validation.php来找到了解决这个问题的方法。

我在第487行将$callback更改为TRUE

$callback = TRUE;

并注释出第488-500行:

    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;
        }
    }

如果有人可以在不编辑CodeIgniter的system文件的情况下考虑解决方案,那么赏金仍然存在。

答案 5 :(得分:0)

function add($id = '') {

    $this->form_validation->set_rules('title', 'Title', 'trim|required');
    $this->form_validation->set_rules('title_description', 'title_description', 'trim|required');
    $this->form_validation->set_rules('color', 'color', 'trim|required');
    $this->form_validation->set_rules('button', 'button', 'trim|required');
    //$this->form_validation->set_rules('description', 'Description', 'trim|required');
    if ($this->form_validation->run() == FALSE) {
        echo "Not Valid";
    } else {
        echo "Valid";
    }
}

答案 6 :(得分:0)

您可以在视图中添加具有永久值的隐藏输入,并在验证规则中对其进行测试。

在视图中:

<input type="hidden" name="id_form" value="1"/>

在模型或控制器中(取决于您的架构)

 public function validates_rules(){
        $this->form_validation->set_rules('id_form', 'Title', 'callback_values_check');
    ...
        }


   public function values_check($id_form){
       if($this->input->post('other_value_to_test')){
...
       }
    }