I've used Codeigniter for a while and whilst I've not always found the form validation as straightforward as I'm sure it should be I've never had any massive problems... until now!
I have a simple form comprised of text inputs and a textarea. The form starts off prepopulated and, if the validation fails, repopulates it with the last changed state.
My problem is this - The textarea needs to accept pound signs (£). It populates text from the database absolutely fine but on submit, whether the form validates or not, it strips them out, regardless of what I do!!
I've scoured the net and can only find solutions about applying things like htmlentities to the validation rules, but if I firephp the post data out, even before the rules, it's already been stripped out.
global_xss_filtering is set to false in my config.
It's driving me mad and wasting way more time than it should... has anyone got a solution to this, I know I'm probably missing something really simple - it's maddening!
Thanks,
Helen
Here's my validation code, although the firephp log at the top shows it to already be stripped out so I can't see how doing anything here will help... I've tried adding the various php function as it suggests HERE (codeigniter manual) but it makes no difference at all.
public function edit_entry2($entry_id, $page_id) {
$this->firephp->log($_POST);
$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Name', 'required|max_length[255]');
$this->form_validation->set_rules('address1', 'Address line 1', 'max_length[255]');
$this->form_validation->set_rules('address2', 'Address line 2', 'max_length[255]');
$this->form_validation->set_rules('address3', 'Address line 3', 'max_length[255]');
$this->form_validation->set_rules('address4', 'Address line 4', 'max_length[255]');
$this->form_validation->set_rules('county', 'County', 'required|max_length[255]');
$this->form_validation->set_rules('post_code', 'Post Code', 'max_length[10]');
$this->form_validation->set_rules('telephone1', 'Telephone 1', 'required|max_length[12]|is_natural');
$this->form_validation->set_rules('telephone2', 'Telephone 2', 'max_length[12]|is_natural');
$this->form_validation->set_rules('fax', 'Fax', 'max_length[12]|is_natural');
$this->form_validation->set_rules('email', 'Email address', 'valid_email');
$this->form_validation->set_rules('website', 'Website', 'max_length[255]');
$this->form_validation->set_rules('rating_awards', 'Rating/Awards', 'max_length[255]');
$this->form_validation->set_rules('description', 'Description', 'max_length[1000]');
$this->form_validation->set_rules('categories[]', 'Categories', 'callback_categories_check');
if ($this->form_validation->run() == FALSE)
{
$this->edit_entry($entry_id, $page_id);
}
else
{
$updated_entry = array('name'=>$_POST['name'], 'address1'=>$_POST['address1'], 'address2'=>$_POST['address2'], 'address3'=>$_POST['address3'], 'address4'=>$_POST['address4'], 'county'=>$_POST['county'], 'post_code'=>$_POST['post_code'], 'telephone1'=>$_POST['telephone1'], 'telephone2'=>$_POST['telephone2'], 'fax'=>$_POST['fax'], 'email'=>$_POST['email'], 'website'=>$_POST['website'], 'rating_awards'=>$_POST['rating_awards'], 'description'=>$_POST['description']);
$this->tourism_catalogue_model->update_entry($entry_id, $updated_entry, $_POST['categories']);
$this->index($page_id);
}
}
You can use validation callbacks. So, when your validation rule is triggered, it will then fire a callback function that you could then use to strip out or inject the pound symbols as desired.
Form Validation Callbacks
Related
I have a bit of problem with Twig in CodeIgniter.
I have tried to integrate Twig in CodeIgniter, so I would have clean templates.
CodeIgniter Simple and Secure Twig
This is really good, it is my first time to use templating engine.
But I encountered a problem. My form validation messages won't show if I submit the form.
public function user_register()
{
$this->form_validation->set_rules('username', 'Username', 'trim|required');
$this->form_validation->set_rules('password', 'Password', 'trim|required');
$this->form_validation->set_rules('email', 'Email', 'trim|required');
$this->form_validation->set_rules('firstname', 'Firstname', 'trim|required');
$this->form_validation->set_rules('lastname', 'Lastname', 'trim|required');
if ($this->form_validation->run() === FALSE) {
$data = [
'title' => 'Register',
];
$this->twig->display('user_register', $data);
}
}
If I do:
<?php echo validation_errors(); ?>
It won't output anything. My observation is, now that I have used Twig for my views, I cannot use php tags. Is it right to assume that?
If yes, how can I output validation errors in CodeIgniter using Twig?
I would appreciate any suggestions, and links that you will post. Hope you can guide me or lead me where to look at.
Thankyou.
Edit
I have tried using {{ validation_errors() }}
But it gives me an error: Please see screenshot:
You can do it using a very simple process like below code -
1. write this code in your controller
$data['errors'] = validation_errors();
$this->twig->display('user_register', $data);
2.
then inside your view, write {{ $errors }}
I have tested it & it's working without any problem.
I finally found the answer. In the package I included in my question, I just edited the file application/libraries/Twig.php:
private $functions_safe = [
'form_open',
'form_close',
'form_error',
'set_value',
'form_hidden',
'validation_errors', /** I just add this line and validation errors worked perfectly */
'form_input',
'form_password',
];
For anyone who will use the package above, hope this helps. Just add the function that you want to use in your view in the $functions_safe array.
Thanks!
I'm writing something where if you select a certain button or dropdown I want to change the rules of a certain field. Basically the logic is, check a button or select an ID from a select and you don't need to populate the address fields. I've been trying to do thing within the form_validation rather than in he controller where I could actually do something like this
if(isset($_POST['checkbox'])){
//check rules
}
So I've done this:
public function check_address($str,$prefix=null){
$this->set_message('check_address','Please select an address or fill out a new one');
//var_dump($this->_field_data);exit;
$remove=array('address_line1','address_line2','address_line3','city','postcode');
if($prefix!==null){
foreach($remove as &$r){
$r=$prefix.'_'.$r;
}
}
unset($r);
foreach($this->_field_data as $key=>$f){
if(in_array($key,$remove)){
unset($this->_field_data[$key]);
}
}
}
This works the way I want it to but I think I've interfered with codeiginter's Form_Validation class as it throws an error stating the required indexes in my array are not set.
The error message
A PHP Error was encountered
Severity: Notice
Message: Undefined index: billing_address_line1
Filename: libraries/Form_validation.php
Line Number: 481
I'm not really too sure how I can achieve what I want to do without interfering with what codeigniter needs? Is there another array I need to remove so that the key isn't sort after?
I've also done this now
foreach($this->_field_data as $key=>&$f){
if(in_array($key,$remove)){
//unset($this->_field_data[$key]);
//str_replace('/required\|/','',$f['rules']);
//str_replace('/required/','',$f['rules']);
foreach($f['rules']as$r=>$val){
$val=strtolower($val);
if($val=='required')unset($f['rules'][$r]);
}
var_dump($f);
}
}
unset($f);
This now does what is required by removing the rule required but the required function I think must've already of run?
Array of rules
$this->con['validation']['checkout']=array(
array('field'=>'address_line1','label'=>'Address line 1','rules'=>'required|min_length[3]|max_length[200]|check_basket'),
array('field'=>'address_line2','label'=>'Address line 2','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'address_line3','label'=>'Address line 3','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'city','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[50]'),
array('field'=>'postcode','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[9]|valid_postcode'),
array('field'=>'shipping_addressID','label'=>'Address','rules'=>'check_address[]'),
array('field'=>'billing_address_line1','label'=>'Billing address line 1','rules'=>'required|min_length[3]|max_length[200]'),
array('field'=>'billing_address_line2','label'=>'Billing address line 2','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'billing_address_line3','label'=>'Billing address line 3','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'billing_city','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[50]'),
array('field'=>'billing_postcode','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[9]|valid_postcode'),
array('field'=>'billing_address_same','label'=>'Billing Address','rules'=>'check_address[billing]'),
array('field'=>'billing_addressID','label'=>'Billing address','rules'=>'check_address[billing]')
);
I think the simplest approach is the best. In the controller, add the rule if the checkbox is checked.
if(isset($_POST['checkbox'])){
$this->form_validation->set_rules('billing_address_line1', 'Billing Address Line 1', 'required');
}
Added after comments and question edited
Still striving for the simplest implementation while avoiding foreach loops using a bunch of string manipulation, and multiple rules arrays that are nearly identical.
This makes use of the fact that form_validation->set_rules() can accept an array in the third argument (instead of the pipe separated string). The string gets turned into an array eventually anyway so starting with an array is more efficient at runtime.
Also in the name of efficient runtime, method chaining is used when setting rules.
Start by creating reusable "rules" arrays to be passed to set_rules().
$rules_address1 = ['required', 'min_length[3]', 'max_length[200]', 'callback_check_basket'];
$rules_address_23 = ['min_length[3]', 'max_length[200]'];
$rules_city = ['required', 'min_length[3]', 'max_length[50]'];
$rules_postcode = ['required', 'min_length[3]', 'max_length[9]', 'callback_valid_postcode'];
$this->form_validation->set_message('required', 'You must provide {field}.');
$this->form_validation
->set_rules('address_line1', 'Address line 1', $rules_address1)
->set_rules('address_line2', 'Address line 2', $rules_address_23)
->set_rules('address_line3', 'Address line 3', $rules_address_23)
->set_rules('city', 'Town/City', $rules_city)
->set_rules('postcode', 'Postal Code', $rules_postcode);
if(!isset($_POST['checkbox']))
{
unset($rules_address1[0]);
unset($rules_address_23[0]);
unset($rules_city[0]);
unset($rules_postcode[0]);
}
$this->form_validation
->set_rules('billing_address_line1', 'Billing Address line 1', $rules_address1)
->set_rules('billing_address_line2', 'Billing Address line 2', $rules_address_23)
->set_rules('billing_address_line3', 'Billing Address line 3', $rules_address_23)
->set_rules('billing_city', 'Town/City', $rules_city)
->set_rules('billing_postcode', 'Postal Code', $rules_postcode);
I skipped rules for the addressID field(s) as I'm not sure how it is used.
Also, per CI SOP, added callback_ to what appeared to me to be custom callback methods. Adjust accordingly.
As you know, this all takes place in the controller before $this->form_validation->run() is called.
Check it from Form validation class. Call your own validation method for rules that you want to delete. https://codeigniter.com/user_guide/libraries/form_validation.html#callbacks-your-own-validation-methods
Then in those methods, check whether Checkbox is checked or not. If checked, skip all rules, and return TRUE from callback function. Something like this:
address_line1_callback_function() {
CI = &get_instance();
if ( CI->input->post('checked') )
return true;
/// Rules for address line go here
}
I'm trying to make a validation for 2 field that must have a different value. I only know how to set the rules for validate matching value.
$this->form_validation->set_rules('book1','Book1','required|matches[book2]');
$this->form_validation->set_rules('book2','Book2','required|matches[book1]');
if I input book1=novel, and book2=novel, the code above will return TRUE.
How can I validate 2 field where the value of each field is not matching each other? So if I input book1=novel and book2=comic, it will return TRUE.
You should use callback_ method for custom validation, CI form validation library does not provide notMatch type validation rule, see below sample code.
$this->form_validation->set_rules('book1','Book1','required');
$this->form_validation->set_rules('book2','Book2','required|callback__notMatch[book1]');
AND place method in controller class
function _notMatch($book2Value, $book1FieldName){
if($book2Value != $this->input->post($book1FieldName){
$this->form_validation->set_message('_notMatch', 'book1 and book2 values are not matching');
return false;
}
return true;
}
In codeigniter 3 you can use the differs[] set rule, to enforce that field values don't match.
$this->form_validation->set_rules('book1', 'Book 1', 'required|differs[book2]');
$this->form_validation->set_rules('book2', 'Book 2', 'required|differs[book1]');
This means you don't need to create an unnecessary callback. However, for older versions you will.
See the documentations for more: Codeigniter 3 Documentation
You can use differs like so:
$this->form_validation->set_rules('password', 'current password', 'max_length[25]|min_length[5]|required');
$this->form_validation->set_rules('new_password', 'new password', 'max_length[25]|min_length[5]|required|differs[password]');
$this->form_validation->set_rules('confirm_password', 'confirm password', 'required|max_length[25]|min_length[5]|matches[new_password]');
I user validation method in my codeigniter project.
In that i set rules for validation like.
$this->form_validation->set_rules('firstname', 'First Name', 'required');
$this->form_validation->set_rules('lastname', 'Last Name', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
Here display three difference errors when validation failed.
I want to display only one error like 'All fields are required' instead of follwing three.
You can add the attribute required in your inputs, so you don't need to send data to the server to get it checked.
<input type="text" name="fieldname" required />
and you'll get on every input a message saying that it's required.
add this line in controller
$this->form_validation->set_message('required', 'All fields are required');
$this->form_validation->set_message('valid_email', 'All fields are required'); // using this we overrideerror message found in the language file
I have a callback function that check_captcha which sees if $row is ==0 or == 1 (this information is queried from sql).
The problem is that I can not call it from $self->form_validation->set_rule('captcha', 'call_back_check_captcha') due to the fact that my function takes in a $row var. The way I'm calling it now I get a Unable to access error message. How can I make this work?
function check_captcha( $row)
{
if($row ==0)//didnt find any
{
$this->form_validation->set_message('captcha', 'text dont match captcha');
return FALSE;
}
else
{
return TRUE;
}
}
function create_member()
{
$past = time() - 7200;
$this->db->query("DELETE FROM captcha WHERE captcha_time <".$past);
$sql = "SELECT COUNT(*) AS count FROM captcha WHERE word =? AND ip_address =?";
$binds = array($_POST['captcha'], $this->input->ip_address(), $past);
$query= $this->db->query($sql, $binds);
$row = $query->row(); //row query rows : if it found an entry =1
$self->check_captcha($row->count);
//VALIDATIONS
$this->form_validation->set_rules('first_name', 'First Name', 'trim|required');
$this->form_validation->set_rules('last_name', 'Last Name', 'trim|required');
$this->form_validation->set_rules( 'email_address', 'Email Address', 'trim|required|valid_email|unique[user.email_address]');
$this->form_validation->set_rules('username', 'Username', 'trim|required|min_length[4]|unique[user.username]');
$this->form_validation->set_rules('password', 'Password', 'trim|required|min_length[4]|max_leng[32]');
$this->form_validation->set_rules('password2', 'Password Confirmation','trim|required|matches[password]');
if(!$_POST['captcha']){
$this->form_validation->set_rules('captcha', 'Captcha','trim|required');}else{
$this->form_validation->set_rules('captcha', 'Captcha', 'callback_check_captcha');}
if($this->form_validation->run()==FALSE)
{ //this -> to the curr obj(UserController) && registraion() points to the the function in controller
$this->registration(); //reloads reg page so they can fill out right stuff
}
else
$this->form_validation->set_message('check_captcha', 'text dont match captcha');
The message name corresponds to the function, not the field. So setting it to "check_captcha" will fix your bug. The error message will use the correct field name.
Actually the best way, instead of write the error message directly on controller, would be add this entry "check_captcha" on languages.
In my case, the message for validation rule (form validation) "less_than" was not present.
I changed the file /system/language/??/form_validation_lang.php. I've added the missing entry.
That helped me
go to application/config/autoload.php and add "Security" helper class there.
$autoload['helper'] = array('security');
Or add this before your form validation
$this->load->helper('security');
You can set error message in set_rules :
$this->form_validation->set_rules('captcha', 'Captcha', 'callback_check_captcha',
array('check_captcha' => 'text dont match captcha'));
add a entry to your language file with named of the part inside the (yourfieldname) of the errormessage - thats solved the problem
Even if the question is already answered, there is another error that can lead to the same error message:
If you call your callback checkCaptcha, it will not work. Prefer always a name like check_captcha as recommended in Codeigniter/General Topics/PHP style guide.