I have this code below. My problem is it only triggers the callback. The required and valid_email rules are not called. I'm expecting to execute the rules in order. But when I remove the callback it runs normal. TIA.
$this->form_validation->set_rules('search_word', 'Email address', 'trim|required|valid_email|callback_has_valid_credentials');
$this->form_validation->set_message('has_valid_credentials', '{field} is not registered in the system.');
if ($this->form_validation->run() == FALSE){
$this->load->view('login/reset');
return;
}
You don't have a function named has_valid_credentials defined.
public function has_valid_credentials($str) {
/** Write validation code here **/
}
For your reference, check out the documentation.
https://www.codeigniter.com/userguide3/libraries/form_validation.html#callbacks-your-own-validation-methods
Related
Why does adding errors to the errors array, outside the after hook of the Illuminate\Validation\Validator Object in Laravel, doesn't trigger the ValidationException exception?
Let's assume I am validating a phoneNumber field from a request with the withValidator method in a form request class. When i add an error to the errors array directly without using the after callback on the validator, the error isn't considered but when i pass it inside the after hook callback the error is recognised. So can someone please explain to me the why because i thought since the errors method is on the Validator object it would be straight forward appended to the errors.
Here the scenario without the after hook: This doesn't work as expected
public function withValidator(Validator $validator)
{
if($validator->fails()){
return;
}
$phoneNumber = $validator->validated()["phoneNumber"];
if(strlen($phoneNumber) != 10){
$validator->errors()->add("phoneNumber","Invalid phone number");
}
}
And here is the one with the after hook: This works as expected
public function withValidator(Validator $validator)
{
if($validator->fails()){
return;
}
$validator->after(function (Validator $validator) {
$phoneNumber = $validator->validated()["phoneNumber"];
if(strlen($phoneNumber) != 10){
$validator->errors()->add("phoneNumber","Invalid phone number");
}
});
}
Most of the articles i read don't tell why we must use the after hook they just put it there so i would like to understand what's the reason. Thanks
If you look at this chapter of the Laravel documentation on validation, you can see that you're supposed to check if ($validator->fails()) after defining your $validator->after() callback.
From what I understand, the $validator->after() method only registers a callback to be executed after the validation is triggered.
The validation actually happens when you call $validator->validated() or $validator->fails(). In your case, you're either calling the fails method before registering your callback (so it won't be executed) or calling the validated method within the callback.
I suggest you register your callback first with $validator->after() and only then should you use $validator->fails() and/or $validator->validated() to execute the validation.
public function withValidator(Validator $validator)
{
// No need to check ->failed() because ->validated() automatically
// returns a response to the user if the validation fails.
$validator->after(function (Validator $validator)
{
// Add your custom validation rules here...
if (strlen($phoneNumber) !== 10)
{
$validator->errors()->add('phoneNumber', 'Invalid phone number');
}
});
// Valdidate the data.
// This line will automatically return a response
// to the user if the validation fails.
$validated = $validator->validated();
// Retrieve the phone number
$phoneNumber = $validated['phoneNumber'];
// Use the validated $phoneNumber here...
}
Hello all i was using form_validation Library in codeigniter inside my application. I am making a password retrieving function. I have made a submit form of the email . Now, on the email input field i want to apply these validations.
required
valid_email
check email exist or not.
For the 3rd one i am using call back function to check the database and it worked fine. But with the call back function valid_email is not functioning. This is my controller functions.
public function password_retrieve()
{
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email|callback__email_exists');
if ($this->form_validation->run() == false) {
$this->load->view('login_header');
$this->load->view('password_retrieve');
$this->load->view('login_footer');
} else {
}
} else {
$this->load->view('login_header');
$this->load->view('password_retrieve');
$this->load->view('login_footer');
}
}
function _email_exists($email)
{
$this->load->model('users_model');
$result = $result = $this->users_model->check_email_is_exist($email);
if (!$result) {
$this->form_validation->set_message(__FUNCTION__, 'This %s address does not exist!');
return false;
} else {
return true;
}
}
It should checked the valid_email rather than the going to the callback function.
In other mean i want to know what is the order of the rules. Is callback rule runs before the valid_email?
Try to remove "trim" and for check if email exist don't use another function. But use "is_unique[table_name.email]".
$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[table_name.email]');
By Searching the official documentation and git repository i have found out that there is not a particular order in which a function will run in codeigniter. This means $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email|callback__email_exists');
In this case valid_email will run after the callback__email_exists. There is not a order in which first trim, then required and then valid_email will run.
So what i have done is to make a new function in my callback function which runs after the required but before the check_email.
Answering this question so that in future people can get the benefit from it. Cheers!
EDIT2: Scroll down for most up-to-date information!
In CodeIgniter 3, I recently moved callback rules across all of my controllers to application/libraries/MY_Form_validation.php to prevent code repetition etc., and to clean up.
Right now, they don't seem to be working anymore.
MY_Form_validation.php starts like this:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
public $CI;
function run($module = '', $group = '')
{
log_message('debug',"Now running the MY_Form_validation");
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
Then a whole list of callback function follows, all defined as public function callback_name(){}.
I also have one (in the same class) which checks if the provided user login information is correct (and thus, if the user can login etc.), but the form validation can't find the rule.
The error log looks like this:
INFO - 2016-06-23 13:33:18 --> Form Validation Class Initialized
DEBUG - 2016-06-23 13:33:18 --> Now running the MY_Form_validation
INFO - 2016-06-23 13:33:18 --> Language file loaded: language/english/form_validation_lang.php
DEBUG - 2016-06-23 13:33:18 --> Unable to find callback validation rule: check_database
The first DEBUG message indicates that MY_Form_validation is loaded (as its overwritten run() method is used, hence the debug logging), but it somehow can't find the callback functions clearly defined below.
I also included language file application/language/english/form_validation_lang.php with the following line:
$lang['form_validation_check_database'] = 'The password does not match the username. Try again.';, which it catches correctly (i.e. this message is displayed when performing the form validation), but it somehow cannot find the callback function itself.
EDIT: I checked to see if methods weren't inherited correctly:
public function __construct($rules = array())
{
$this->CI =& get_instance();
var_dump(get_class_methods($this));
The var_dump() does output the correct, full array of methods, both my own custom callbacks and the built-in ones.
EDIT2:
I read the system/libraries/Form_validation.php and investigated where the debug message occurs, which can be seen in this code sample (line 734-749) :
// Call the function that corresponds to the rule
if ($callback OR $callable !== FALSE)
{
if ($callback)
{
if ( ! method_exists($this->CI, $rule))
{
log_message('debug', 'Unable to find callback validation rule: '.$rule);
$result = FALSE;
}
else
{
// Run the function and grab the result
$result = $this->CI->$rule($postdata, $param);
}
}
It seems as though callbacks are only looked for in the main CI object, but not in the form validation library itself. I could add some hacky exceptions that would pick the library callbacks, but I doubt that that's the best thing to do and I guess I'm overlooking something simple...
If any additional info is required, please let me know.
Alright, I found out...
Apparently, as soon as you move callback functions to MY_Form_validation.php, they are actually built-in validation rules, and no longer act as callbacks.
When setting form rules, I still had the callback_ prefix applied, which makes the Form_validation library look for the rule in the normal CI object (i.e. in the controller) rather than the (MY_)Form_validation class.
The fix for me was to simply remove this prefix from the applied validation rule settings. Now it finds the 'callback' functions correctly.
Please Try This
<?php
class Form extends CI_Controller {
public function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|is_unique[users.email]');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
public function username_check($str)
{
if ($str == 'test')
{
$this->form_validation->set_message('username_check', 'The {field} field can not be the word "test"');
return FALSE;
}
else
{
return TRUE;
}
}
}
?>
I have the following form validation:
$this->CI->form_validation->set_rules(
'email', 'lang:email', 'callback_validate_email');
In the same controller I have the following function (excuse the debugging here):
public function validate_email($string) {
echo 'test val';
exit;
$valid = $this->CI->force_model->validate_email($string);
if(!$valid) {
$this->CI->form_validation->set_message('validate_email', 'lang:email');
return false;
} else {
return true;
}
}
My issue is, the function is never called via the callback. Could anyone suggest what the issue might be here?
I saw someone else having this problem, and strangely they were also using $this->CI->...
Their solution was to extend the Validation library and add your custom validation callback there. More info here: CodeIgniter Validation in Library does not accept callback
Does it work if you set the form validation rules using $this->form_validation->... instead? E.g.
$this->form_validation->set_rules(
'email', 'lang:email', 'callback_validate_email');
I have a helper function that checks if a username is valid.
In helper file:
if ( ! function_exists('valid_username'))
{
function valid_username($username)
{
$ci=& get_instance();
$ci->load->database();
if (empty($username) OR !preg_match("/^[a-z]([0-9a-z_-])+[0-9a-z]$/i", $username)) //Allowed a-z, 0-9, and underscores. Must end in a-z or 0-9.
{
$ci->form_validation->set_message('valid_username', 'Characters not valid.');
return FALSE;
}
$ci->db->select('username');
$ci->db->where('username', $username);
$ci->db->where('activated', 1);
$ci->db->where('banned', 0);
$ci->db->limit(1);
$query = $ci->db->get('users');
if ($query->num_rows() > 0) //if user exists
{
return TRUE;
}
else
{
$ci->form_validation->set_message('valid_username', 'The %s does not exist.');
return FALSE;
}
}
}
In my controller I am adding the helper to my form validation:
$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|min_length[2]|max_length[50]|callback_valid_username');
//add callback from helper function
function valid_username($username)
{
return valid_username($username);
}
This works well however I have to make the callback private like so:
$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|min_length[2]|max_length[50]|callback__valid_username');
function _valid_username($username)
{
return valid_username($username);
}
After making the callback private I get the following message upon submitting an invalid username:
Unable to access an error message corresponding to your field name.
What am I doing wrong here?
I'm not 100% sure why making the function private ruined your error messages, but I can suggest a workaround:
Form validation rules permit any function that accepts up to 1 parameter to be used as a validation or prep rule. So basically, anything that's available to the current script is available as a form validation rule as well, including your valid_username() function. Try this (just add it to your other rules):
$this->form_validation->set_rules('username', 'Username', 'valid_username');
So, you don't need the controller method as a wrapper, and you don't need to use callback_.See if that works for you.
Aside: I would suggest skipping the function_exists() call when you define valid_username(), unless you're sure you want to allow the function to be "overwritten".
You can use anything that is callable as a rule. Even if it is a function in a helper. Check it out
The right syntax is:
$this->form_validation->set_rules(
'username', 'Username', array('required', array('valid_username_callable', 'valid_username')));
In the helper, set error message if necessary like this:
$CI = &get_instance();
$CI->form_validation->set_message('valid_username_callable', 'Error message');