Hey guys!
I work at a company that hosts multiple CI sites, and they work lovely. But some of these sites are user input heavy (i.e. lots of forms).
Traditionally the way to define multiple validation rulesets has been sub arrays:
http://www.codeigniter.com/userguide3/li...s-of-rules
However this quickly leads to verbose "sets" with repeating fields. Example:
PHP Code:
$config = array(
'signup1' => array(
array(
'field' => 'emailaddress',
'label' => 'EmailAddress',
'rules' => 'required|valid_email'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
),
'signup2' => array(
array(
'field' => 'title',
'label' => 'Title',
'rules' => 'required'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
)
);
An alternative to this would be to add a "groups" key to each array, where you can declare what group(s) a field belongs to:
PHP Code:
$config = array(
array(
'field' => 'emailaddress',
'label' => 'EmailAddress',
'rules' => 'required|valid_email',
'groups' => 'signup1'
),
array(
'field' => 'title',
'label' => 'Title',
'rules' => 'required',
'groups' => 'signup2'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required',
'groups' => 'signup1|signup2'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required',
'groups' => 'signup1|signup2'
)
);
To test this idea i've build an extension to the form_validation library (largely a copy of the system run function) :
PHP Code:
class MY_Form_validation extends CI_Form_validation {
protected $CI;
public function __construct($config = array())
{
parent::__construct($config);
$this->CI =& get_instance();
}
public function run_group($group = '')
{
// Do we even have any data to process? Mm?
$validation_array = empty($this->validation_data) ? $_POST : $this->validation_data;
if (count($validation_array) === 0)
{
return FALSE;
}
// Does the _field_data array containing the validation rules exist?
// If not, we look to see if they were assigned via a config file
if (count($this->_field_data) === 0)
{
// No validation rules? We're done...
if (count($this->_config_rules) === 0)
{
return FALSE;
}
// New group array key support. From these values create a new temporary group.
// Then use this new group as validation group. When empty, validate the whole config file.
foreach($this->_config_rules as $config_item)
{
if(isset($config_item['groups']))
{
$groups = explode('|', $config_item['groups']);
foreach($groups as $value)
{
if($value == $group)
{
$temp_config_array[] = $config_item;
}
}
}
}
$this->set_rules(isset($temp_config_array) ? $temp_config_array : $this->_config_rules);
// Were we able to set the rules correctly?
if (count($this->_field_data) === 0)
{
log_message('debug', 'Unable to find validation rules');
return FALSE;
}
}
// Load the language file containing error messages
$this->CI->lang->load('form_validation');
// Cycle through the rules for each field and match the corresponding $validation_data item
foreach ($this->_field_data as $field => $row)
{
// Fetch the data from the validation_data array item and cache it in the _field_data array.
// Depending on whether the field name is an array or a string will determine where we get it from.
if ($row['is_array'] === TRUE)
{
$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
}
elseif (isset($validation_array[$field]) && $validation_array[$field] !== '')
{
$this->_field_data[$field]['postdata'] = $validation_array[$field];
}
}
// Execute validation rules
// Note: A second foreach (for now) is required in order to avoid false-positives
// for rules like 'matches', which correlate to other validation fields.
foreach ($this->_field_data as $field => $row)
{
// Don't try to validate if we have no rules set
if (empty($row['rules']))
{
continue;
}
$this->_execute($row, $row['rules'], $this->_field_data[$field]['postdata']);
}
// Did we end up with any errors?
$total_errors = count($this->_error_array);
if ($total_errors > 0)
{
$this->_safe_form_data = TRUE;
}
// Now we need to re-set the POST data with the new, processed data
$this->_reset_post_array();
return ($total_errors === 0);
}
}
The new call would now be:
PHP Code:
$this->form_validation->run_group('signup1');
This extension seems to work nicely, but i wonder if any of you can poke some holes in it. I wouldn't want to continue if it ends up being a bad idea. As my colleague said; there is probably a good reason why this isn't the default way Codeigniter handles groups.
Also this might help others who've had / have similar issue's. All thoughts are welcome
Regards,
Stephan