I'm running CI form validation and using form_error() to display errors individually for each field. The problem, though, is that the form_error() function only returns the first validation error
Example field:
<input type="text" name="value" value="short">
validation script:
$validationRules = "min_length[6]|numeric";
$this->form_validation->set_rules(
'value',
'lang:mod_the_field',
$validationRules
);
if($this->form_validation->run() === FALSE){
echo form_error('value');
}
The above outputs: <p>The Value field must be at least 5 characters in length.<\/p>
Although the field also fails validation as a numeric value.
I cannot seem to find documentation on this. Is there a simple step I am missing to get all validation errors for a single field output? Is there a better solution than running the validation multiple times, once for each rule?
EDIT:
To be clear, the output I'm looking for in this particular example is:
<p>The Value field must contain only numbers.</p>
<p>The Value field must be at least 5 characters in length.</p>
One solution is to run the validation once for each rule and aggregate the output, but I'm trying to find out if there is a way to do this out of the box in CI?
SOLUTION:
I checked the Form_validation library and found that Samutz' comment is correct. The script breaks out and returns after the first validation error.
rather than extending any classes, I changed my code to iterate over each rule and concatenate the error string like so:
$validationRules = "min_length[6]|numeric";
$validationRules = explode('|', $validationRules);
$errors = '';
foreach($validationRules as $rule){
$this->form_validation->set_rules(
'value',
'lang:mod_the_field',
$rule
);
if($this->form_validation->run() === FALSE){
$errors .= form_error('value');
}
}
$errors = ($errors) ? $errors : FALSE;
echo $errors;
The problem
When testing for errors in a CI form that errors served by validation_errors() in form helper are not exactly what I would call 'accessible'.
Sure they are neat in the way that there's an error message presented for every error (so failing to populate both user name and password when they are required, will display two error messages by default), but this should be taken a step further. I'm talking about error labels, e.g.:
<label for="password">The Password field must be at least 6 characters in length</label>
So users can click on error and get straight to field that needs fixing.
The idea
My first idea was to write a wrapper for form helper or somehow extend the form class. While this seemed as a good solution, a deeper study of validation class usage revealed a quicker fix. By default, rule for password could look like this:
$this->form_validation->set_rules('password', 'Password', 'trim|required|min_length[6]|md5');
Where set_rules() method parameters are as follows:
Password field name attribute (the same which you've defined)
Quoting the manual - A "human" name for this field, which will be inserted into the error message.
Validation rules for password field (in the above example password is required and at least 6 characters long) plus some modifiers (trimming spaces and instant conversion to md5).
A simple solution is to insert a label into second parameter, which will be literally used for displaying the error. It could look like this:
$this->form_validation->set_rules('password', '<label for="password">Password</label>', 'trim|required|min_length[6]|md5');
But why not take it a step further and use form_label() from form helper? That would result in:
$this->form_validation->set_rules('password', form_label('Password', 'password'), 'trim|required|min_length[6]|md5');
As you've probably noticed, the fix will result in a slightly different code that we were aiming at:
The <label for="password">Password</label> field must be at least 6 characters in length
Only the actual field name is wrapped in label tag. But hey - with some simple styles (below) it's not that bad at all. For more organised styles it would be nice to add a custom class to that label, or better yet - wrap the whole error message in some unique container (so you'll be able to specify styles only for that error label) using set_error_delimiters():
$this->form_validation->set_error_delimiters('<div class="form_error">','</div>');
That will result in following html:
<div class="form_error">The <label for="password">Password</label> field must be at least 6 characters in length</div>
Add some styles to that:
.form_error label {color:#F00;text-decoration:underline}
Hope you can do more with form_error() at this point:
// in stylesheet
.form_error label {color:#F00;text-decoration:underline}
// in form controller
$this->form_validation->set_error_delimiters('<div class="form_error">','</div>');
$this->form_validation->set_rules('password', form_label('Password', 'password'), 'trim|required|min_length[6]|md5');
just stumbled upon this myself and found a way around it. It's not really an orthodox solution but here it is
$errors = validation_errors('/', '/');
$errors = explode("/", $errors);
echo $errors[1];
This will only output the first error in the array.
EDIT: Make sure you check if your array has more than 1 value in it
if(count($errors) > 1) {
echo $errors[1];
}
first error
second error
box p:nth-child(2){display: none;}
Related
PHP Controller:
$this->form_validation->set_rules('phone', $this->language->get_text('phone', 'global'), 'max_length[0]');
I need to put an IF condition for the above line code to return this:
if (The_Above_Line_Code is NOT empty)
{
$this->output->set_status_header(400);
exit;
}
So, if the input field don't contain characters it's OK and the contact form to work properly, but if contain characters, then should return a blank page (set_status_header(400)).
PS: It's a way to combat spam in contact form.
$this->form_validation->set_rules('phone', $this->language->get_text('phone', 'global'), 'max_length[0]|numeric');
If it's not a number then form validation fails. I don't see the logic in serving a 400.
https://www.codeigniter.com/userguide3/libraries/form_validation.html?highlight=form%20validate#rule-reference
Update
After understanding your reasoning better you can simply do this:
if (!empty($this->input->post('phone'))) {
show_404(); // sets header + exits
}
You can even use show_404() (CI function) as a way to log the error: show_404('bot detected', true);.
My form has a cellphone and a phone field. I want the user to fill either one of the fields, or both, but not neither.
I've seen ways to do it in other languages, but could I have some advice on how to do it with Codeigniter?
You can do it as:
$this->form_validation->set_rules('phone', 'Your validation message.', 'callback__phone_check');
And make a function:
function _phone_check() {
//check for phone and cellphone field.
//make sure one field is not empty and return accordingly
}
Hope that helps
Just wanted to throw some quick code snippets your way. I wanted to accomplish this and this question was one of the first entries in google when I did my search. I took inspiration from the other answers and here's what I did which worked for me (YMMV):
$this->form_validation->set_message('contactVerify', 'Either Phone or Email is required');
...
$this->form_validation->set_rules('phone', 'Phone', 'trim|callback_contactVerify[email]|xss_clean');
$this->form_validation->set_rules('email', 'Email', 'trim|callback_contactVerify[phone]|valid_email|xss_clean');
...
public function contactVerify($contact, $otherField) {
return ($contact != '' || $this->input->post($otherField) != '');
}
Since this is a very simple validation function, I pre-set the error message so I don't have to set it inside validation function. I pass in the other field I want to check as the second argument via the square brackets.
Hope this is useful.
Just do a JS validation on client-side, and PHP validation on server-side (or use CI's form helper)... Anyway, PHP should look something like this:
if ($_POST['cellphone'] == '' OR $_POST['phone' == '') {
// do stuff like make an notification, alert, etc... and take users back to the form
}
On my website, I have user accounts that are configurable with forms that allow users to update everything from first and last names to privacy settings. I use the following function to update the database with that input. (Note that the following code uses WordPress-specific features.)
function update_account() {
global $current_user; get_currentuserinfo();
require_once( ABSPATH . WPINC . '/registration.php' );
$uid = $current_user->ID;
// First Name
if(isset($_POST['first_name']) && $_POST['first_name'] <> $current_user->first_name) {
wp_update_user( array(
'ID' => $uid, 'first_name' => esc_attr($_POST['first_name'])
));
}
// ...and so on 43 more times...
}
This feels like the wrong way to process forms. This also looks like it will negatively impact server performance when there are multiple users and frequent updates, given that the if-then-else conditions for every field, even fields not on a particular page, force checking each field for input.
Moreover, since form data can be expected to remain relatively constant, I added the <> operator to prevent the function from updating fields where there has not been any change, but I suspect this also means that every field is still evaluated for change. To make matters worse, adding new fields -- there are already 44 fields in total -- is an unwieldy process.
What's a better way to process form data?
Keep an array of the fields you will be processing with this code, and iterate over it. This works if all your attributes are strings, for example. If you have different data types such as boolean flags to handle differently from the strings, you may wish to group them into their own array.
// All the fields you wish to process are in this array
$fields = array('first_name', 'last_name', 'others',...'others99');
// Loop over the array and process each field with the same block
foreach ($fields as $field) {
if(isset($_POST[$field]) && $_POST[$field] != $current_user->{$field}) {
wp_update_user( array(
'ID' => $uid, $field => esc_attr($_POST[$field])
));
}
}
There's a lot of things missing with your implementation. I don't know what kinds of data you're allowing the user to manipulate but most usually have some kind of requirements to be acceptable. Like not having certain characters, not being blank, etc. I don't see any validation occurring, so how do you handle values that might be undesirable? And what happens when you receive bad data? How do you inform the user of the bad data and prompt them to correct it?
If we abstract the situation a bit we can come up with generalizations and implement an appropriate solution.
Basically form fields [can] have a default value, a user specified value [on form review], validation requirements and validation errors [with messages]. A form is a collection of fields that upon form submit needs to be validated and if invalid, re-displayed to the user with instructive corrective prompts.
If we create a form class that encapsulates the above logic we can instantiate and use it to pass around our controller/views. Oops, I was just assuming you were using an Model/View/Controller type framework, and I'm not really familiar with wordPress so I don't know if that is exactly applicable. But the principle still applies. On the page where you both display or process the form, here's some pseudo logic how how it might look.
function update_account()
{
// initialize a new form class
$form = new UserAccountInfoForm();
// give the form to your view for rendering
$this->view->form = $form;
// check if form was posted [however your framework provides this check]
if(!Is_Post())
return $this->render('accountform.phtml');
// check if posted form data validates
if(!$form->isValid($_POST))
{
// if the form didn't validate re-display the form
// the view takes care of displaying errors, with the help of its
// copy of the $form object
return $this->render('accountform.phtml');
}
// form validated, so we can use the supplied values and update the db
$values = $form->getValues(); // returns an array of ['fieldname'=>'value']
// escape the values of the array
EscapeArrayValues($values);
// update db
wp_update_user($values);
// inform the user of successful update via flash message
$this->flashMessage('Successfully updated profile');
// go back to main profile page
$this->redirect('/profile');
That makes your controller relatively clean an easy to work with. The view gets some love and care to, utilizing the $form value to display the form correctly. Technically, you can implement a method in the form class to give you the form html, but for simplicity I'm just going to assume your form html is manually coded in accountform.phtml and it just uses $form to get field info
<form action='post'>
<label>first name</label> <input class='<?=$this->form->getElement('first_name')->hasError() ? "invalid":""?>' type='text' name='first_name' value="<?=$this->form->getElement('first_name')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('first_name')->getError()?></span><br/>
<label>last name</label> <input class='<?=$this->form->getElement('last_name')->hasError() ? "invalid":""?>' type='text' name='last_name' value="<?=$this->form->getElement('last_name')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('last_name')->getError()?></span><br/>
<label>other</label> <input class='<?=$this->form->getElement('other')->hasError() ? "invalid":""?>' type='text' name='other' value="<?=$this->form->getElement('other')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('other')->getError()?></span><br/>
<input type='submit' value='submit'/>
</form>
Here the pseudo code relies on the form class method "getElement" which returns the field class instance for the specified field name (which would be created an initialized in the constructor of your form class). Then on the field class methods "hasError" and "getError" to check if the field validated correctly. If the form has not be submitted yet, then these return false and blank, but if the form was posted and invalid, then they will have been set appropriately in the validate method when it was called. Also "getValue" would return either the value supplied by the user when the form was submitted, or if the form has not been submitted, the default value as specified when the field class was instantiated and initialized.
Obviously this pseudo code is relying on a lot of magic that you'd have to implement if you roll your own solution--and it's certainly doable. However, at this point I'll direct you to the Zend Framework Zend_Form components. You can use zend framework components by themselves without having to utilize the entire framework and application structure too. You might also find similar form component solutions from other frameworks but I wouldn't know about those (we are a Zend Framework shop at my work place).
Hopefully this hasn't been too complicated, and you know where to go from here. Of course just ask if you need any clarification.
Basically I have several big forms (lot of fields submitted) that need to be processed, which are very similar but may differ by one or two fields. Firstly all fields get escaped and assigned to a variable of their original name (thus $_POST['f_name'] will be $f_name).
Then I need to validate the data, things like certain obligatory fields must be present, certain fields much match (confirming password/email), certain fields must pass regex check. I do this via a long if/else statement, where each failure has it's own error message.
Now of course I would like to avoid this repetition of the clumsy code, and replace it with some looping function, which will be easier to edit and maintain.
However this poses a bit of a problem, especially performing the checks and assigning individual error messages.
I would be keen to hear suggestions as how would you approach developing such validation/error reporting function.
Here is a short version of what the code looks like:
$name = mysqli_real_escape_string($mysqli, $_POST['name']);
$password = mysqli_real_escape_string($mysqli, $_POST['password']);
$password_re = mysqli_real_escape_string($mysqli, $_POST['password_re']);
if ($name == '') :
$data = "Please enter name";
elseif ($password != $password_re) :
$data = "Passwords don't match";
endif;
First off I would make a function to clean your post array.
$clean_post = sanitize($_POST);
function sanitize($input) {
if (is_array($input)) {
foreach($input as $var=>$val) {
$output[$var] = sanitize($val);
}
}
else {
if (get_magic_quotes_gpc()) {
$input = stripslashes($input);
}
$input = cleanInput($input);
$output = mysql_real_escape_string($input);
}
return $output;
}
Next I would add divs with the same name as the field and set error variable within the $data array and remove the ifs in between them, personally I hate being spoon fed my form errors.
if ($name == '')
$data['name'] = "Please enter name";
if ($password != $password_re)
$data['password] = "Passwords don't match";
Finally, I would set the content of the divs to the $data array value.
<div><?=$data[name];?></div>
<input type="text" name="name" value="<?=$clean_post[name];?>">
<div><?=$data[password];?></div>
<input type="password" name="password" value="<?=$clean_post[password];?>">
<input type="password" name="password_re" value="<?=$clean_post[password_re];?>">
Hope this helps
I'm not sure that there's one cut-and-dried approach to this problem. Here's how my company has addressed this problem:
1) Front side validation. Yes, can be bypassed. However, if you're only using it as the first line of defense it's a great solution (and acceptable to some of my biggest clients including an international banking group) I love the simplicity of Cedric Dugas' inline validation script because it's basically just a few extra characters per field. Another HUGE benefit to the inline validation--it allows us to use one centralized alert area for server-side validation errors along with a simple alert trigger via css on individual elements, while the majority are caught inline and alerted which is FAR more user friendly.
2) A class that deals with "stuff" We refer to it as the "garbage in, garbage out" It takes an array of post data, sets fields based on element names, and deals accordingly. This includes data sanitizing, validations, etc. The problem with validations is that unless you have generic types data to validate, you can get into a lot of specifics which can really gum up code in a hurry. Also, this can make you actually have to do MORE work on the front end because your field names have to line up accordingly. In our case, we deal with external webform responses from clients a lot who don't necessarily appreciate the need for standardized naming of fields, and that can get to be a headache.
3) "Chunking" sections. On huge form scenarios, we've resorted to "chunking" submits in phases via Ajax to minimize the damage to the server done in one big submit. So, user updates profile information, submit happens. User does background info section, update happens...etc. It's not right for all situations, but is some it can work well...and it allows progressive validation as you move from start to finish. I certainly wouldn't ever recommend this approach for each individual question, though.
4) "Forced Sanitation" Sounds evil, huh? In cases such as zip codes, addresses, etc you can simply fix information for the client. Rather than barking about a missing Zip Code, you can get it automatically, correct 100% of the time. That's the beauty of Google and the USPS--they're free and smarter than the average user.
I'd say it's better to do this on the client side using a javascript form validator, before anything gets submitted. Do a search for javascript form validation. It'll save you a page load and force your users to correct errors before even submitting. Here's a simple example of one way, taken from the first google hit for "javascript form validation":
<form name="myForm" action="demo_form.asp" onsubmit="return validateForm()" method="post">
First name: <input type="text" name="fname">
<input type="submit" value="Submit">
</form>
<script language="javascript">
function validateForm()
{
var x=document.forms["myForm"]["fname"].value
if (x==null || x=="")
{
alert("First name must be filled out");
return false;
}
}
</script>
I'm trying to create a fairly simple form that has a few checkboxes and input fields and a textarea. Nothing is required by itself; however, if 'A' checkbox is checked, then 'A' input field is required (and so on for the couple other checkboxes I have).
I have the above functionality in place, but I'm having a tough time figuring out how to have an error returned if the form is submitted blank (since nothing is required by default).
Does anyone know of an easy-ish solution for this? It seems like it should be so simple...
Thanks
I assume that your using the form_validation class..
You will need to write a callback that does something like this:
function _checking()
{
if (isset($_POST['a_checkbox']))
{
if (empty($_POST['a_text_field']))
{
$this->form_validation->set_message('_checking', 'this should not be empty');
return FALSE;
}
return TRUE;
}
}
I hope this is what you are looking for..
Just check if $_POST-array is empty, except for your submitbutton?