如何使 CodeIgniter 可调用留空的复选框,自定义表单验证错误
How to make CodeIgniter callable work for checkboxes that are left empty, custom form validation bug
我的表单验证规则有问题(在单独的配置文件中)。这发生在复选框中。
为了组织我的验证规则,我创建了一个名为 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.
?>
$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;
}
}
这应该可以解决问题。
再说一遍,希望对小伙伴有帮助。
您可以在 /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 将使用它。
一个这样的例子
application/controllers/Shop
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
application/libraries/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';
}
}
好的,我设法解决了我的问题。这里的问题是因为我怀疑 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
returns 应用于此数组时为 false,因此跳过了验证。
相关文档:http://www.codeigniter.com/user_guide/libraries/form_validation.html#callable-use-anything-as-a-rule
解决方法
就我个人而言,我没有看到上述代码的使用,因为我不想在未发布字段时跳过验证。所以我通过创建 MY_Form_validation
class 并覆盖 _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.
我的表单验证规则有问题(在单独的配置文件中)。这发生在复选框中。
为了组织我的验证规则,我创建了一个名为 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.
?>
$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;
}
}
这应该可以解决问题。
再说一遍,希望对小伙伴有帮助。
您可以在 /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 将使用它。
一个这样的例子
application/controllers/Shop
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
application/libraries/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';
}
}
好的,我设法解决了我的问题。这里的问题是因为我怀疑 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
returns 应用于此数组时为 false,因此跳过了验证。
相关文档:http://www.codeigniter.com/user_guide/libraries/form_validation.html#callable-use-anything-as-a-rule
解决方法
就我个人而言,我没有看到上述代码的使用,因为我不想在未发布字段时跳过验证。所以我通过创建 MY_Form_validation
class 并覆盖 _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.