Welcome Guest, Not a member yet? Register   Sign In
Pass error to form (validation_errors) if the whole form fails from the database query?
#1

[eluser]Sven Delle[/eluser]
I can validate all fields in a form just fine. But how do I pass a 'custom' - in this case a login failure - error to the form if the user is not found in the database - all fields will pass just fine, as they contain data in the 'right' format?

Code:
[...]

// user login fails (user not found in database)
$this->form_validation->custom_error('Login failed ...'); // Something like this
$this->index; // returning user to login form

[...]

How do I pass something like 'Login failed' on to the form, to show exactly as other native validation errors, as in running:

Code:
echo validation_errors();
Hope my question is clear.
#2

[eluser]Sven Delle[/eluser]
Does this question really cause that much silence?

I would have thought this would be a natural part of 'form_validation', but it seems not.

It should be simple to actually revisit the form with some custom errors set, right?
#3

[eluser]backtoeleven[/eluser]
Hi Sven,

Does't the Setting Error Messages help with this?

If you have a password field you would do a callback to a function that checks the credentials against the database, if that fails you would use the set_message function to return an error to the form.

Hope that helps a bit.
#4

[eluser]Sven Delle[/eluser]
I've tried a lot of different things, this is one of them:

If the login fail (but the form validates)

Code:
$this->form_validation->set_message('login_failure', 'Login failed');
$this->index();

Where index loads a view containing the form.

And in the for I've tried:

Code:
if(form_error())
{
echo '<div id="errors">' . form_error('login_failure') . '</div>';
}

and plain:

Code:
echo '<div id="errors">' . form_error('login_failure') . '</div>';

I ALSO have this in the form view:

Code:
if(validation_errors())
{
echo '<div id="errors">' . validation_errors() . '</div>';
}

Where I guess ANY validation_error would show up - native or custom.
#5

[eluser]backtoeleven[/eluser]
The login form I have created recently I have the following:

Login Controller

Code:
public function login()
{
  if($this->input->post())
  {
   $this->form_validation->set_rules('user_email', 'email', 'trim|required|xss_clean|valid_email');
   $this->form_validation->set_rules('user_password', 'password', 'trim|required|xss_clean|callback_auth');
  
   if ($this->form_validation->run() == false)
   {
    $this->template->render('access/login');
    return false;
   }
   else
   {
    redirect('');
   }
  }
  else
  {
   $this->template->render('access/login');
  }
}

The above performs a call back to the following function:

Code:
public function auth()
{
  $user_email=$this->input->post('user_email');
  $user_password=$this->input->post('user_password');
  
  $data = array(
   'user_email'=>$user_email,
   'user_password'=>md5($user_password)
  );
  
  $this->load->model('access_model');
  $result = $this->access_model->login($data);
  
  if($result)
  {
   $data = array();
   foreach($result as $row)
   {
    if($row->user_status == '0')
    {
     $this->form_validation->set_message('auth', 'Your account has not been activated, please check for your activation email. ' . anchor('access/resend','Resend it?'));
     return FALSE;
    }
    else
    {
     $data = array(
      'user_auth' => TRUE,
      'user_id' => $row->user_id,
      'user_name' => $row->user_name,
      'user_email' => $row->user_email,
     );
    $this->session->set_userdata($data);
    }
   }
   return TRUE;
  }
  else
  {
   $this->form_validation->set_message('auth', 'Invalid username or password. Please check your details and try again. ' . anchor('access/reset','Reset Account?'));
   return FALSE;
  }
}

As you can see, I set some custom error messages which I then display in the view using the standard form_error() methods. These are set depending on the response from my model when checking the user credentials with the database.

One thing that caught me out was ensuring that I set the first param of the set_message method to the same as the callback method (in this case 'auth').
#6

[eluser]backtoeleven[/eluser]
It might be worth pasting in the function from your controller and view for us to see exactly what it is you have and hopefully steer you in the right direction.
#7

[eluser]boltsabre[/eluser]
That's an option, the only downside to that is it will make a db call to authenticate everytime time the form is submitted and the password validations passes up to "callback_auth" rule. So that means if the user doesn't enter any email, its a db hit, if they enter "myusername" its a db hit, if they enter "myemail@" it's a db hit (so long as something is entered in the password field).

You could do this in your login controller
Code:
$this->form_validation->set_rules('user_email', 'email', 'trim|required|xss_clean|valid_email');
$this->form_validation->set_rules('user_password', 'password', 'trim|required|xss_clean');

if ($this->form_validation->run() === true) {
   //form passed, now we know we have a valid email address and a password.
   $run = $this->user_model->authenticate($this->input->post('user_email'), $this->input->post('user_pword'));
   if($run === true){
      //login sucessful, redirect them to where ever they need to go
      redirect(.....);
   }else{
      //login failed, reload form with error message
      $data['login_failed'] = 'The email/password you supplied does not match any records in our database';
   }
}
$this->load->view('view_name');

And in your view just display $login_failed where you want to!
#8

[eluser]Sven Delle[/eluser]
Thank you all. backtoeleven and boltsabre both have useful things.

I want the error to act exactly as all other validation errors, so I'm sure gonna go for the set_message version. And also making sure we have valid data before we hit the database.

What seems somewhat illogical to me is that you tie a general form validation check to one specific field - in this case the password field. I think this is what triggers this question that often in these forums. But I guess that's the way things have to work, as there probably wouldn't be a general routine for it.

But if you look at it from a usability (for programmers) perspective, the concept »Form Validation« make one expect that a functionality like this was integrated (somehow). But if you go nitty gritty on it, it does make sense. As »Form Validation« would only validate the form itself - as in "have we got VALID information in itself" - not necessarily considering »Database Validation«.

So maybe we could come up with a more specific wording for the routine?

Ok, that's only being old and pedantic, sorry!
#9

[eluser]backtoeleven[/eluser]
Another way of approaching this is to do two step validation i.e. check the information is valid, then check the information against the database (if step 1 passes). This way you are only hitting the database once and you can utilise the set_message method.

I've reworked by above code so does just this...

Code:
public function login()
{
  if($this->input->post())
  {
   $this->form_validation->set_rules('user_username', 'username', 'trim|xss_clean|required|alpha_dash|min_length[4]');
   $this->form_validation->set_rules('user_password', 'password', 'trim|xss_clean|required|alpha_dash|min_length[4]');

   if ($this->form_validation->run() == FALSE)
   {
    $this->template->render('access/login');
   }
   else
   {
    $this->form_validation->set_rules('user_password', 'password', 'callback__authenticate');
    if ($this->form_validation->run() == FALSE)
    {
     $this->template->render('access/login');
    }
    else
    {
     redirect('');
    }
   }
  }
  else
  {
   $this->template->render('access/login');
  }
}

As you can see the second pass validates on one rule which is a simple callback to the _authenticate function where you would perform your checks against the database and provide a simple TRUE/FALSE return value. Depending on the that return you either set_message and show the form, or let the user in.

The only problem with this way of doing things is that you are increasing your overheads by hitting the validation routines twice.
#10

[eluser]Aken[/eluser]
I do something similar to what boltsabre posted in that I check for normal validation before querying the DB for valid details. I also extended the form validation library with a method that allows me to add error messages at any point. This doesn't affect the run() functionality, but does allow me to add errors to the validation_errors() or similar functions.

Keep in mind that set_message() does not TRIGGER an error, it only sets the error text. It is designed to let you customize the text of error messages only.




Theme © iAndrew 2016 - Forum software by © MyBB