编辑表单时,Codeigniter验证唯一字段的问题

时间:2016-06-10 19:15:43

标签: forms codeigniter validation

我在applications/config/form_validation.php中有一个单独的文件用于验证。用于创建新用户的两个字段必须是唯一的,他们的身份证和电子邮件。

'user' => array(
    array(
        'field' => 'email',
        'label' => 'E-MAIL',
        'rules' => 'required|valid_email|is_unique[usuario.email]'
    ),
    array(
        'field' => 'cpf_cnpj',
        'label' => 'CPF',
        'rules' => 'required|_validate_cpf|is_unique[usuario.cpf_cnpj]'
    ),
    ...
)

一开始,我使用了同一组验证来编辑表单,但我对这两个字段都有问题,因为他们总是被指责不是唯一的。

所以,我在表单中添加了一个hidden字段来存储这些字段的当前值并添加另一个字段,同时存储该值,但是在视图中显示的字段将是唯一的字段编辑,然后,在edit方法中,在继续检查hidden字段是否与常规字段不同之前会发生一个条件:

// HTML
<input type="email" name="novoemail" class="email <?php echo form_error('novoemail') ? 'campo_aviso' : ''; ?>" value="<?php echo $u['email']; ?>"/>
<input type="hidden" name="email" value="<?php echo $u['email']; ?>"/>

// In `edit`
if ($this->input->post('email') !== $this->input->post('novoemail')) {
    $this->form_validation->set_rules('email', 'E-MAIL', 'is_unique[usuario.email]');
}

if ($this->form_validation->run('edit_user')) { ... }

如果发现差异,请添加规则以使其唯一。现在的问题是,任何差异,即使输入的电子邮件不存在,也会失败,并指责不是唯一的。

我需要找到一种方法来编辑唯一字段,并且仍然保证唯一性。

2 个答案:

答案 0 :(得分:1)

我不同意这种方法。如果is_unique规则失败,你应该找出原因,而不是试图解决它。

无论如何,我想你需要在验证规则上运行某种类型的连接回调。我发现验证数组很笨重,所以我不会使用它们。请随意改编:

$this->form_validation->set_rules('test', 'Test Post', 'trim|less_than[99]'.($this->input->post('test') === $this->input->post('test2' ? 'required' : '')));

这可能是一个更好的答案,也许某种方式来使用内置的&#34;匹配&#34;验证规则。我在一个CI项目中把它扔了,它没有抛出任何错误,但我也没有在合法数据上测试它。

答案 1 :(得分:1)

我同意这种方法。使用隐藏字段的想法将起作用,对于确定与form_validation->run()一起使用的正确规则集非常有用。

这个答案坚持使用规则的配置文件,并避免直接使用set_rule()

您可以轻松地操纵config/form_validation.php中的数组以返回所需的集合,同时不会有一堆重复的代码。

考虑此版本的config/form_validation.php

$check_email = array(
    'field' => 'novo_email',
    'label' => 'E-MAIL',
    'rules' => 'trim|required|valid_email|is_unique[usuario.email]'
);

$check_card = array(
    'field' => 'novo_cpf_cnpj',
    'label' => 'CPF',
    'rules' => 'trim|required|_validate_cpf|is_unique[usuario.cpf_cnpj]'
);

$config = array(
    'edit_email' => array($check_email),
    'edit_cpf_cnpj' => array($check_card),
    'new_user' => array($check_email, $check_card)
);

上面创建了三组独立的规则,并没有重新创建代码结构。

只有两种情况甚至需要执行字段验证。

  1. 新用户
  2. 其中一个或两个字段已更改
  3. 如果对于新用户,您始终将隐藏字段的值设置为空字符串(或NULL)&#34;新用户&#34;状态很容易确定。在这种情况下,你需要&#34; new_user&#34;配置文件中的规则。

    如果隐藏字段不为空,则需要确定哪些字段已更改,并根据找到的内容选择验证规则。

    这里是如何在edit函数中实现该逻辑的。注意:novo_*字段是用户编辑的字段。

    public function edit()
    {
      //instead of multiple calls to $this->input->post, 
      //capture all the inputs in one handy array
      $posted = $this->input->post();
    
      //check for new user (true when the hidden field 'email' is blank
      //if 'email' is blank then 'novo_cpf_cnpj' should be too
      if(empty($posted['email']))
      {
        $rules = 'new_user';
      }
      else  //not a new user. What has changed?
      {
        //note the use of trim - in case user added spaces to an otherwise unchanged field
        $changed_email = $posted['email'] !== trim($posted['novo_email']);
        $changed_cpf_cnpj = $posted['cpf_cnpj'] !== trim($posted['novo_cpf_cnpj']);
        if($changed_email && $changed_cpf_cnpj)
        {
          //both have changed, treat like a new user
          $rules = 'new_user';
        }
        elseif($changed_email)
        {
          $rules = 'edit_email';
        }
        elseif($changed_cpf_cnpj)
        {
          //only possibility left - cpf_cnpj is changed
          $rules = 'edit_cpf_cnpj';
        }
      }
    
      if(! isset($rules) )
      {
        //Not a new user and nothing changed so validation is not needed.
        //Behave as if successful validation occurred and redirect to successful save page
        redirect('controller/save_success');
        //redirect() does not return because it always calls the PHP 
        //function exit thereby ending script execution.
        //So, there is no need for an else to if(!isset($rules))
      }
    
      if($this->form_validation->run($rules))
      {
      //save to database then
      redirect('controller/save_success');
      }
      //whatever happens when validation fails
    }