如何使 CodeIgniter 可调用为空的复选框,自定义表单验证错误

Posted

技术标签:

【中文标题】如何使 CodeIgniter 可调用为空的复选框,自定义表单验证错误【英文标题】:How to make CodeIgniter callable work for checkboxes that are left empty, custom form validation bug 【发布时间】:2015-12-04 02:51:09 【问题描述】:

我的表单验证规则有问题(在单独的配置文件中)。复选框会发生这种情况。

为了组织我的验证规则,我创建了一个名为 validation_rules 的库文件。这个库包含我所有的自定义回调,如valid_date 等。为了能够调用这些规则,我加载了库,然后使用以下配置:

array(
    'field' => 'terms',
    'label' => 'lang:reg_lbl_terms',
    'rules' => array(array('terms_accepted', array($ci->validation_rules, 'terms_accepted')))
    ),

其中$ci 是对 CodeIgniter ($this) 的引用。

现在这适用于大多数类型的输入,但它不适用于留空的复选框,可能是因为它们没有被发布。

但是,当我放弃我的库并简单地将回调添加到控制器时,使用以下配置一切正常:

array(
    'field' => 'terms',
    'label' => 'lang:reg_lbl_terms',
    'rules' => array('callback_terms_accepted')
    ),

此外,当我在 rules 数组(或字符串)的任何位置添加规则 required 时,确实会调用 required 规则(返回 false,因为未选中复选框),但所有其他规则都完全忽略。

这一定是 CodeIgniter 的错误吧?有人有解决方案或解决方法吗?当然this是一个选项,但我真的不喜欢它。

相关文档:http://www.codeigniter.com/user_guide/libraries/form_validation.html

编辑: 复选框 php/HTML:

<?php
$data = array(
    'name'    => 'terms',
    'value'   => 'true'
);
echo form_checkbox($data);
// Results in: <input type="checkbox" name="terms" value="true">
// No set_value() is used.
?>

【问题讨论】:

你能把你的复选框的html代码贴出来吗?以及你如何在其中使用set_value @Saty Yep,将其编辑到问题中。 请阅读this *** 仅用于帮助解决您编写的代码的问题。它不是报告错误的地方。在 CodeIgniter 论坛和/或 GitHub 页面上直接向开发人员报告错误,以便为所有人评估和修复。 【参考方案1】:

好的,我设法解决了我的问题。这里的问题是我怀疑 CodeIgniter 中存在与可调用对象相关的错误。

注意:此错误似乎已在 CI 3.0.1+ 中修复。我运行的是 3.0.0 版。

问题

问题在于 Form_validation 库在 _execute 函数中有一段代码,用于检查是否存在 required 规则或未发布字段的回调规则集。这适用于复选框,因为它们在留空时不属于 $_POST 数组。这是导致问题的代码:

$callback = FALSE;
if ( ! in_array('required', $rules) && ($postdata === NULL OR $postdata === ''))

    // Before we bail out, does the rule contain a callback?
    foreach ($rules as &$rule)
    
        if (is_string($rule))
        
            if (strncmp($rule, 'callback_', 9) === 0)
            
                $callback = TRUE;
                $rules = array(1 => $rule);
                break;
            
        
        elseif (is_callable($rule))
        
            $callback = TRUE;
            $rules = array(1 => $rule);
            break;
        
    

    if ( ! $callback)
    
        return;
    

如果不需要或有回调,此代码用于完全跳过对字段的验证。 然而,CI 开发人员错误地使用is_callable 检查回调。这对于结构如下的普通可调用对象当然很好:

array($this->some_model_or_library, 'function_name')

但是,CodeIgniter 允许您为回调命名,以便为它设置验证错误,如下所示:

array('my_callback_function', array($this->some_model_or_library, 'function_name'))

不出所料,is_callable 在应用于此数组时返回 false,因此会跳过验证。

相关文档:http://www.codeigniter.com/user_guide/libraries/form_validation.html#callable-use-anything-as-a-rule

解决方案

就个人而言,我没有看到上述代码的用途,因为我不想在未发布字段时跳过验证。所以我通过创建一个MY_Form_validation 类并覆盖_execute 函数解决了这个问题,只需将代码替换为:

$callback = TRUE;

当然,稍微保守一点的解决方案是检查多维数组并将is_callable 应用于适当的元素,如下所示:

if (is_callable($rule)                            // Original check.
|| (is_array($callback) && is_array($callback[1]) // Check if the callback is an array and contains an array as second element.
&& is_callable($callback[1]))                     // Check if the second element is a callable.

【讨论】:

【参考方案2】:

您可以在 /config 内的 form_validation 文件中创建规则

application/config/form_validation.php

$config = array(
    'controller/method' => array(
        array('field'=>'', 'label'=>'', 'rules'=>'required|acceptTerms')
        array('field'=>'another', 'label'=>'', 'rules'=>'required')
    ),
);

注意 controller/method 的键,如果你没有在调用 form_validation 函数中专门设置它,Codeigniter 将使用它。

这样的例子是这样的

应用程序/控制器/商店

class Shop extends CI_Controller

    public function __construct() parent::__construct(); 

    public function index()
    
        // Show the Purchase Form
        // in some view
        return $this->load->view();
    

    public function purchase()
    
        // notice we don't pass any params to the run() function
        // codeigniter will look inside application/config/form_validation/$config
        // for any matching key, ie: shop/purchase

        if(!$this->form_validation->run()) 
            // If validation fails, show the form again
            // and stop the method from executing any further
            return $this->index();
        
    

为了验证是否设置了复选框,我们查找关键字on

应用程序/库/MY_Form_validation.php

class MY_Form_validation extends CI_Form_validation

    public function __construct($config)
    
        parent::__construct( $config );
    

    public function acceptTerms( $field )
    
        $this->set_error('acceptTerms', 'your error message');

        return (bool) $field == 'on';
    

【讨论】:

【参考方案3】:
$terms = $this->input->post('terms');
var_dump((int)$checked); //Just to see the value, then remove this line.
if((int)$checked == 1) 
  //Checked = True
 else 
  //Checked = False

我将检查所需的标志并编辑此答案。

编辑: 不要只使用required,而是尝试使用required|isset,然后在执行callback_terms_accepted 时,执行以下操作:

function terms_accepted($value) 
  if (isset($checked)) 
    return true;
   else 
    $this->form_validation->set_message('terms_accepted', 'Error message');
    return false;
  

这应该可以解决问题。

再次,希望对伴侣有所帮助。

【讨论】:

以上是关于如何使 CodeIgniter 可调用为空的复选框,自定义表单验证错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在 VB.NET 中将可为空的 DateTime 设置为空?

更新查询使 Codeigniter PHP 中 MySQL 的记录为空

如何使我的字符串属性可以为空?

vue添加第一行为空的多选框

Codeigniter 的 zip 下载文件为空

声明为不可为空的 Kotlin 属性即使具有初始化值也可以为空