CodeIgniter Forums

Full Version: Form validation returning FALSE
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I am undertaking a migration of a project from CI 2.2.x to 3.1.6 and am stuck on validation of an e-mail address on a password reset form.

Below is my code.  This works perfectly in 2.2.x but validation returns false in 3.1.6:
PHP Code:
        if (isset($_POST['email']) && !empty($_POST['email'])) {
            
$this->load->library('form_validation');
            
$this->form_validation->set_rules('email''Email''trim|required|valid_email');
            if (
$this->form_validation->run() == FALSE)
            {
                
$data['errors'] = 'E-mail address you provided is not valid.';
                
$data['inset_content']    = $this->load->view('login/inset_obtain_email_password_reset'$dataTRUE);
                
$this->load->view('view_login_template'$data);
            } else {
                
$email        trim($this->input->post('email'));
                
$user        $this->model_reset_password->email_exists($email);
                if (
$user) {
                    
$this->send_reset_password_email($email,$user['first_name'],$user['salt']);
                }
                
$data['inset_content']    = $this->load->view('login/inset_reset_password_email_sent'$dataTRUE);
                
$this->load->view('view_login_template'$data);
            }    
        } else {
            
$data['inset_content']    = $this->load->view('login/inset_obtain_email_password_reset'$dataTRUE);
            
$this->load->view('view_login_template'$data);
        }
//if 


The problem seems to lie in the new methods for validation core/Form_validation.php public function run() line 422:
PHP Code:
    public function run($group '')
    {
        
$validation_array = empty($this->validation_data)
            ? 
$_POST
            
$this->validation_data;

        
// Does the _field_data array containing the validation rules exist?
        // If not, we look to see if they were assigned via a config file
        
if (count($this->_field_data) === 0)
        {
            
// No validation rules?  We're done...
            
if (count($this->_config_rules) === 0)
            {
                return 
FALSE;
            }
... 

The $validation_array is set set correctly from the $_POST data but the _field_data array is empty.  

I have tried setting rules using the array method and the cascade method as outlined in the Form Validation docs for 3.1.6 and they are not being set under core/Form_validation.php public function set_rules.  CI sees no POST data $this->validation_data as empty.

PHP Code:
    public function set_rules($field$label ''$rules = array(), $errors = array())
    {
        
// No reason to set rules if we have no POST data
        // or a validation array has not been specified
        
if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
        {
            return 
$this;
        } 


Is there something I am missing?

Thanks for taking the time to read this.
Really does look like set_rules() is not getting the job done. $this->_field_data is populated by set_rule(). Can you step through in debug mode and see what's happening?
Does your input have the correct name set, ie name="email"
I discovered why FALSE is being returned but am at a loss to explain CI's state at the time my application seeks to validate the email address.

In core/Form_validation.php @ line 167 we have `public function set_rules`
PHP Code:
    public function set_rules($field$label ''$rules = array(), $errors = array())
    {
        
// No reason to set rules if we have no POST data
        // or a validation array has not been specified
        
if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
        {
            return 
$this;
        } 


For that first if, $this->CI->input->method() must equal 'post'.  The value is derived from $_SERVER['REQUEST_METHOD'].  For some reason in my application the value is 'GET' [Case is irrelevant. method() does a case conversion on the value].  That state is despite having values in $_POST placed there by a form submission.  I also know the data is in $_POST at the the time form validation runs after this set_rules function. Yes, PaulD name does equal 'email' in the $_POST and validation rule.

In core/Form_validation.php public function run() line 422:

PHP Code:
    public function run($group '')
    {
        
$validation_array = empty($this->validation_data)
            ? 
$_POST
            
$this->validation_data
$validation_array gets its data from $_POST.

From research as to how CI sets $_SERVER['REQUEST_METHOD']='POST' CI does so with the form helper using the form_open() function to create a semantic form opening tag with a method equal to 'post'.

For now, this is my code: 

PHP Code:
    if (isset($_POST['email']) && !empty($_POST['email'])) {
        
$_SERVER['REQUEST_METHOD']='POST'//added this as band-aid
        
$this->load->helper('form');
        
$this->load->library('form_validation');
        
$this->form_validation->set_rules('email''E-mail''trim|valid_email|required');
        if (
$this->form_validation->run()==FALSE) {
            
$data['errors'] = 'E-mail address you provided is not valid.';
            
$data['inset_content']    = $this->load->view('login/inset_obtain_email_password_reset'$dataTRUE);
            
$this->load->view('view_login_template'$data);
        } else {
            
$email        trim($this->input->post('email'));
            
$user        $this->model_reset_password->email_exists($email);
            if (
$user) {
                
$this->send_reset_password_email($email,$user['first_name'],$user['salt']);
            }
            
$data['inset_content']    = $this->load->view('login/inset_reset_password_email_sent'$dataTRUE);
            
$this->load->view('view_login_template'$data);
        }
//if
    
}//if 

I added $_SERVER['REQUEST_METHOD']='POST';.  The validation rule sets, validation can run and return TRUE.

If someone can think of the reason $_SERVER['REQUEST_METHOD'] would equal GET, please enlighten me.

I have another CI application which uses 3.0.6.  That application also has a password reset system but the code is very different from the one above.  Stepping through that code for form validation of a submitted e-mail address, $_SERVER['REQUEST_METHOD'] equals 'POST' as set by CI.  
You have just confirmed that "email" is set and not empty in the $_POST array, but $this->CI->input->method() !== 'post' in set_rules()? That does not make sense.

What does $_SERVER contain just before you explicitly set $_SERVER['REQUEST_METHOD']='POST';?

Does it look the same once you are in set_rules()?

Care to share the relevant part of the form's view? Or, at least confirm that the form method="post".
(10-15-2017, 11:46 AM)dave friend Wrote: [ -> ]You have just confirmed that "email" is set and not empty in the $_POST array, but $this->CI->input->method() !== 'post' in set_rules()? That does not make sense.

What does $_SERVER contain just before you explicitly set $_SERVER['REQUEST_METHOD']='POST';?

Does it look the same once you are in set_rules()?

Care to share the relevant part of the form's view? Or, at least confirm that the form method="post".

If I look at $_SERVER before or after the form is submitted it reads $_SERVER['REQUEST_METHOD']='GET';. At the point in the code after the form is submitted, when `if (isset($_POST['email']) && !empty($_POST['email']))` is TRUE, $_SERVER['REQUEST_METHOD']='GET';.

The only point in my code a SuperGlobal variable is manipulated by my code is the band-aid solution of `$_SERVER['REQUEST_METHOD']='POST'`.

$this->CI->input->method() !== 'post' in set_rules() does make sense if you look at the full context of 'public function set_rules' in core/Form_validation.php @ line 167 
PHP Code:
    public function set_rules($field, $label = '', $rules = array(), $errors = array())
    {
        // No reason to set rules if we have no POST data
        // or a validation array has not been specified
        if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
        {
            return $this;
        } 
... 

if $this->CI->input->method() == 'get' it does not equal post.  The other half is true as well so the result is to not set validation rules for CI thinks there is nothing in $_POST.

The band-aid solution of $_SERVER['REQUEST_METHOD']='POST'; satisfies $this->CI->input->method() in set_rules for it does equal 'post' and will go on to perform the rest of the function (symbolized by '...' in PHP code above.)
(10-15-2017, 01:06 PM)dwlamb Wrote: [ -> ]$this->CI->input->method() !== 'post' in set_rules() does make sense if you look at the full context of 'public function set_rules' in core/Form_validation.php @ line 167 
PHP Code:
    public function set_rules($field, $label = '', $rules = array(), $errors = array())
    {
        // No reason to set rules if we have no POST data
        // or a validation array has not been specified
        if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
        {
            return $this;
        } 
... 

if $this->CI->input->method() == 'get' it does not equal post.  The other half is true as well so the result is to not set validation rules for CI thinks there is nothing in $_POST.

CI knows nothing about the contents of the $_POST array yet in the conditional above. It only looks to see if
  1. The server received a POST request and
  2. The user has not provided an array of data to be validated instead of $_POST

When I said "That does not make sense." it was in reference to the server method.  What does not make sense is that the $_POST superglobal is set, but the server method is GET. The $_POST superglobal should be empty if the method is GET. Yet, it was confirmed that $_POST['email'] is set and not empty.

Something else is at play here.
(10-15-2017, 06:01 PM)dave friend Wrote: [ -> ]Something else is at play here.

Agreed.  I am at a loss to explain how CI is arriving to this state.
I'm highly confident that CI does not:
  • Change the value of $_SERVER['REQUEST_METHOD']
  • Put data in the $_POST array when the request method is "GET"
  • Put data in the $_GET array when the request method is "POST"
Have you used your browser's developer tool to examine and confirm the request "type" of the submit?

Here are things I would check
  1. Hacked core files
  2. Extended core classes
  3. Custom classes / helpers
  4. Framework Hooks used
  5. Some javascript weirdness
  6. Redirect in .htaccess changing a POST to a GET
  7. Other .htaccess weirdness
  8. PHP version and/or config
  9. Server type, version and/or config
I have the same issue, upgrading from 2.x to 3.x. I wanted to say thanks for posting and I am off to try the bandaid mentioned.  Please PM me if you would like to discuss anything about this issue.  Update Thu Apr 18,  

I tried the the bandaid mentioned
it got me farther along

I tried this: 

Changing my  <form action="xxxxxxxx" method="POST">  to 
<form action="xxxxxxxx" method="post"> 

 My headers  for  form submission:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


[HTML Tidy] <form> attribute value "POST" must be lower case for XHTML

it did not work
Pages: 1 2