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');
Related
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!
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
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 tried extending the Laravel 4.2 validation to check if all form data is valid (not just some fields) according to some business rules.
I could not extend the custom validator in any normal way (either too hacky or not DRY enough) so I decided to add the business rules check after validator succeeds, and then add my own error messages and redirect.
It is still ugly and it does not work but for now I would be happy if someone tells me how to add my message to the session. If you feel like telling me how I should use Laravel's custom validators I've included some more code so you can be more specific..:
$validator = Validator::make(Input::all(), $this->validationRules, $this->validationMessages);
if ($validator->fails()) {
if (0 == $id) {
return Redirect::route('x.create')->withErrors($validator)->withInput();
} else {
return Redirect::route('x.edit', $id)->withErrors($validator)->withInput();
}
} else {
//TESTs
if ($this->AlreadyExists($id)) {
$messages = new MessageBag();
if ($request->getSession()->get('errors')){
$messages = $request->getSession()->get('errors')->getBag('default');
}
$messages->add('form', 'same data already exists');
if (0 == $id) {
return Redirect::route('x.create')->withErrors($messages)->withInput();
} else {
return Redirect::route('x.edit', $id)->withErrors($messages)->withInput();
}
}
}
//all is ok. Save/update entity
...
The code for setting the session is first 5 lines after check for AlreadyExists. I got it from some forum but it doesn't seem to work ok (I get some "non-object" exceptions if I include the code so it seems it corrupts the session object)
I don't think I have time to upgrade to L5.
I solved this by creating a new error message bag and adding it to redirect:
$mb = new Illuminate\Support\MessageBag();
$mb->add("form", "same data already exists");
...
return Redirect::route('x.create')->withErrors($mb)->withInput();
Seems I needed to add full namespace for bag, but most of all I needed rest :)
The validation logic is still bad but no time to tinker with that now.
for anyone who uses form request I suggest to take a look at this implementations. formatErrors in laravel 5.1 documentations mentioned for a way to manipulate the way errors display. I just simply jump in it and added some codes to extend errors.
use Illuminate\Contracts\Validation\Validator;
class ProfileChangePasswordRequest extends Request
{
public function authorize()
{
if (auth()->check())
return true;
return false;
}
public function rules()
{
return [
'password' => "required|confirmed|min:6"
];
}
protected function formatErrors(Validator $validator)
{
if ($this->isCurrentPasswordValidate()) {
return $validator->errors()->all();
} else {
$validator->errors()->add('current_password', 'current password is wrong');
return parent::formatErrors($validator);
}
}
public function isCurrentPasswordValidate()
{
return auth()->validate(['email' => auth()->user()->email,
'password' => $this->current_password]);
}
}
Well I have set validationErrors for login in my UsersController:
public function login() {
if ($this->request->is('post')) {
$this->User->set($this->request->data);
if ($this->User->validates() && $this->Auth->login()) {
$this->set('ui', $this->Auth->user('id'));
$this->Session->setFlash(__('Loged in!'), 'flash_success');
$this->redirect($this->Auth->redirect());
} else {
$errors = $this->User->validationErrors;
}
}
}
Now how can I use $error in my view or as an element to be listed above my form?
Plz help I have searched a lot, but the answers were for old CakePHP, and I am using CakePHP 2.3.8.
Validation errors are available in the view automatically
There is no action required to get validation errors in the view, as they are a property of the view class. They can be inspected simply with:
debug($this->validationErrors);
In the view.
But you probably don't need to access them
Note however that it's not normal to need to look at this property directly. Using the form helper errors are displayed automatically, or you can generate errors individually
if ($this->Form->isFieldError('email')) {
echo $this->Form->error('email');
}