Как заставить CodeIgniter запускать пользовательские правила в полях, которые не имеют required
правила, но пользователь остается пустым ?
Лучшее, что я могу придумать, это добавить пространство в поле, если строка пуста, а затем добавить правило trim
– но это кажется взломанным.
Поле требуется только в том случае, если другое поле имеет определенное значение:
// 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; }
Поле требуется только в том случае, если в базе данных существует регулярное выражение:
// 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; }
Зачем нужна другая функция для простой задачи. Используйте, если if..else
Предполагая, что если значение input1
имеет значение равно value1
, тогда вы должны установить только правильное правило проверки для другого ввода, который, как говорят, 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! } } } }
Из кода проблема, которую вы указываете, заключается в том, что вам НЕОБХОДИМО сделать поле обязательным. Ну, сделайте своеобразное обязательное поле с новым правилом: «keep_checking». Таким образом, вы вынуждаете систему проверять все, что хотите. Что я сделал:
application/libraries
В последнем случае, после расширения класса 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; } } } }
ОБНОВИТЬ:
Линия флажка избегала проверки. Просто добавьте новую строку, которую я добавил, и она будет работать. Вы должны добавить правило 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 входит в папку библиотек
Я думаю, что вы ищете callbacks
Вы можете определить обратные вызовы в своем правиле
$this->form_validation->set_rules('field1', 'Field 1', 'trim|callback_field1_check'); $this->form_validation->set_rules('field2', 'Field 2', 'callback_field2_check');
И теперь у вас может быть функция с возвратным значением boolean.
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; }
Я разработал способ сделать это самостоятельно, отредактировав system/libraries/Form_validation.php
.
Я изменил $callback
на TRUE
в строке 487:
$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; } }
Баунти по-прежнему стоит, если кто-то может подумать о решении без редактирования system
файлов CodeIgniter.
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"; } }
Вы можете добавить скрытый ввод в представление с постоянным значением и проверить его при проверке правил.
Ввиду:
<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')){ ... } }