Reputation: 22674
I have a text input where users submit CSV e.g. red, blue, red, yellow
If the user submits duplicate values for instance red
as seen above I want to remove the duplicate. I started making a callback but I'm not sure how to complete it.
//callback rule
function _remove_dublicate($str)
{
$val = strtolower($str); //make everything lowercase
$colors = str_getcsv($val); //create array
$result = array_unique($colors); //remove duplicates
}
If there are duplicates, what should I do to submit the new string from $result
to the database?
Below is my form validation
$this->form_validation->set_rules('colors', 'Colors', 'trim|required|xss_clean|regex_match[/^[a-z, ]+$/i]|callback__remove_dublicate');
if ($this->form_validation->run() == FALSE) //if validation rules fail
{
$this->load->view('edit/form');
}
else //success
{
$data = array (
'colors' => $this->input->post('colors')
);
$this->My_model->colors_update($data);
}
EDIT
based on Cabaret's suggestion I added this in the else
statement for removing dublicates
$colors = str_getcsv($this->input->post('colors')); //create array
$result = array_unique($colors); //remove duplicates
$comma_separated = implode(",", $result); //add back CSV string
$data = array (
'colors' => $comma_separated
);
It seems to work
Upvotes: 3
Views: 4249
Reputation: 102755
Despite the comments, this is a perfectly valid reason to use a callback, similar to the "prep" rules that actually change the value of the input submitted (for instance: trim, xss_clean, strtolower).
You're on the right track, all you have to do is return $result
in your callback and it will alter the input, but make sure you return a string. Example:
//callback rule
function _remove_duplicate($str = '')
{
$val = strtolower($str); //make everything lowercase
$colors = str_getcsv($val); //create array
// you could also use explode(',', $colors)
// if you aren't expecting other delimiters than a comma
// i.e. no commas within quotes
$result = array_unique($colors); //remove duplicates
$result = implode(',', $result); // back to string value
return $result; // Return the value to alter the input
}
Now, if you wanted to warn the user that there are duplicates instead of simply removing them, just return FALSE
if any are found, maybe with count($colors) === count($result)
while $result
is still an array. It's up to you, but just so you know the option to return true/false or alter the input is available.
You could actually write something like this into a new form validation rule within the Form_validation class itself (extend the library, or even just a global function) and not need to use callbacks, it seems like it would be a very reusable function.
This is considered a "prep" rule. From the User Guide:
In addition to the validation functions like the ones we used above, you can also prep your data in various ways. For example, you can set up rules like this:
$this->form_validation->set_rules('username', 'Username', 'trim|required|min_length[5]|max_length[12]|xss_clean');
$this->form_validation->set_rules('password', 'Password', 'trim|required|matches[passconf]|md5');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'trim|required');
$this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email');
In the above example, we are "trimming" the fields, converting the password to MD5, and running the username through the "xss_clean" function, which removes malicious data.
Any native PHP function that accepts one parameter can be used as a rule, like htmlspecialchars, trim, MD5, etc.
Note: You will generally want to use the prepping functions after the validation rules so if there is an error, the original data will be shown in the form.
So, after you've checked that the input is valid, you can proceed to clean it, trim, remove duplicates from a comma separated string, or anything you want. Any globally available functions are valid (including non-native PHP functions, for example: any of CI's helper functions, as long as they are loaded and defined.), as well as any functions that belong to the Form_validation library or any extension of it you may have.
One thing to be aware of: If the function does not exist or is not available, it will be silently ignored. Always test to make sure you are getting the correct results.
Hope this clears up some confusion.
Upvotes: 7
Reputation: 12038
Personally, I would take the callback method out and handle this later on, after the form validation passed. I don't think there's a way to return the result array form the callback. At least the Userguide doesn't specify anything about it. Callbacks for the Form Validation library are only meant to return either true
or false
, I think.
I would just put a function call that checks for duplicates into your else
and always run it there before inserting the data into the DB.
Maybe someone with more CI expertise knows of a better way, but that's how I would do it.
Upvotes: 2