基于此documentation,如何将第二个参数传递给规则方法?
这是我的自定义规则
public function email_exists($email, $exclude_id=NULL)
{
if ( $exclude_id !== NULL ) $this->db->where_not_in('id', $exclude_id);
$result = $this->db->select('id')->from('users')->where('email', $email)->get();
if ( $result->num_rows() > 0 ) {
$this->form_validation->set_message('email_exists', '{field} has been used by other user.');
return FALSE;
} else {
return TRUE;
}
}
这就是我从控制器中调用它的方式
$rules = [
[
'field' => 'email',
'label' => 'Email',
'rules' => [
'required',
'trim',
'valid_email',
'xss_clean',
['email_exists', [$this->m_user, 'email_exists']]
]
]
];
$this->form_validation->set_rules($rules);
如何将第二个参数传递给email_exists方法?
答案 0 :(得分:1)
按照文档中所述,以正确的方式(至少对于CI 2.1+):
$this->form_validation->set_rules('uri', 'URI', 'callback_check_uri['.$this->input->post('id').']');
// Later:
function check_uri($field, $id){
// your callback code here
}
如果这不起作用,请在表单中为$exclude_id
创建隐藏字段,并通过
$exclude_id = $this->input->post('exclude_id');//or whatever the field name is
更多here
答案 1 :(得分:1)
它似乎CI没有为此提供机制。我找到了几种方法来解决这个问题。第一种方法,您可以破解文件系统(Form_validation.php)并在第728行修改一些脚本
if ( preg_match('/(.*?)\[(.*)\]/', $rule[1], $rulea) ) {
$method = $rulea[1];
$extra = $rulea[2];
} else {
$method = $rule[1];
$extra = NULL;
}
$result = is_array($rule)
? $rule[0]->{$method}($postdata, $extra)
: $rule($postdata);
您可以通过第二种方式扩展CI_Form_validation核心并在其中添加自定义规则。我在codeigniter documentation上找到了有关此内容的详细信息。
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
public function __construct()
{
parent::__construct();
}
public function check_conflict_email($str, $exclude_id=NULL)
{
if ( $exclude_id !== NULL ) $this->CI->db->where_not_in('id', $exclude_id);
$result = $this->CI->db->select('id')->from('users')->where('email', $str)->get();
if ( $result->num_rows() > 0 ) {
$this->set_message('check_conflict_email', '{field} has been used by other user.');
return FALSE;
} else {
return TRUE;
}
}
}
/* End of file MY_Form_validation.php */
/* Location: ./application/libraries/MY_Form_validation.php */
第三种方式,我认为这是最好的方法。感谢skunkbad提供solution
$rules = [
[
'field' => 'email',
'label' => 'Email',
'rules' => [
'required',
'trim',
'valid_email',
'xss_clean',
[
'email_exists',
function( $str ) use ( $second_param ){
return $this->m_user->email_exists( $str, $second_param );
}
]
]
]
];
答案 2 :(得分:0)
我使用CI 3.1.10,并且此问题仍然存在,我扩展了库并使用与回调相同的方式
array('username_callable[param]' => array($this->some_model, 'some_method'))
扩展的Form_validation库:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation {
/**
* Executes the Validation routines
*
* @param array
* @param array
* @param mixed
* @param int
* @return mixed
*/
protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
{
// If the $_POST data is an array we will run a recursive call
//
// Note: We MUST check if the array is empty or not!
// Otherwise empty arrays will always pass validation.
if (is_array($postdata) && ! empty($postdata))
{
foreach ($postdata as $key => $val)
{
$this->_execute($row, $rules, $val, $key);
}
return;
}
$rules = $this->_prepare_rules($rules);
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 && 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
{
// If we get an array field, but it's not expected - then it is most likely
// somebody messing with the form on the client side, so we'll just consider
// it an empty field
$postdata = is_array($this->_field_data[$row['field']]['postdata'])
? NULL
: $this->_field_data[$row['field']]['postdata'];
}
// Is the rule a callback?
$callback = $callable = FALSE;
if (is_string($rule))
{
if (strpos($rule, 'callback_') === 0)
{
$rule = substr($rule, 9);
$callback = TRUE;
}
}
elseif (is_callable($rule))
{
$callable = TRUE;
}
elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))
{
// We have a "named" callable, so save the name
$callable = $rule[0];
$rule = $rule[1];
}
// Strip the parameter (if exists) from the rule
// Rules can contain a parameter: max_length[5]
$param = FALSE;
if ( ! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match))
{
$rule = $match[1];
$param = $match[2];
}
elseif ( is_string($callable) && preg_match('/(.*?)\[(.*)\]/', $callable, $match))
{
$param = $match[2];
}
// Ignore empty, non-required inputs with a few exceptions ...
if (
($postdata === NULL OR $postdata === '')
&& $callback === FALSE
&& $callable === FALSE
&& ! in_array($rule, array('required', 'isset', 'matches'), TRUE)
)
{
continue;
}
// Call the function that corresponds to the rule
if ($callback OR $callable !== FALSE)
{
if ($callback)
{
if ( ! method_exists($this->CI, $rule))
{
log_message('debug', 'Unable to find callback validation rule: '.$rule);
$result = FALSE;
}
else
{
// Run the function and grab the result
$result = $this->CI->$rule($postdata, $param);
}
}
else
{
$result = is_array($rule)
? $rule[0]->{$rule[1]}($postdata, $param)
: $rule($postdata);
// Is $callable set to a rule name?
if ($callable !== FALSE)
{
$rule = $callable;
}
}
// 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;
}
}
elseif ( ! 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))
{
// Native PHP functions issue warnings if you pass them more parameters than they use
$result = ($param !== FALSE) ? $rule($postdata, $param) : $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);
$result = FALSE;
}
}
else
{
$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)
{
// Callable rules might not have named error messages
if ( ! is_string($rule))
{
$line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)';
}
else
{
$line = $this->_get_error_message($rule, $row['field']);
}
// 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], $this->_field_data[$param]['label']))
{
$param = $this->_translate_fieldname($this->_field_data[$param]['label']);
}
// Build the error message
$message = $this->_build_error_msg($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;
}
}
}
}