james the seventh
james the seventh

Reputation: 228

CakePHP 2.3 form not showing validation errors

I have been trying to debug this for about two days and have read every answer to this question on the internet... and still can't get it to work.

In my CakePHP app I have a user sign-up form, which uses a model called User and the Form helper. When validation fails, the form does not show any of the validation errors.

The $this->User->validationErrors array is properly populated before the view is rendered, according to debug(), and the fact that the model does not validate is detected by $this->User->save().

Here's my view:

<?php
echo $this->Form->create('User');
echo $this->Form->input('soton_username', array('label' => 'Email address', 'after' => '@soton.ac.uk'));
echo $this->Form->input('username', array('label' => 'Choose a username'));
echo $this->Form->input('password');
echo $this->Form->input('password_confirm', array('label' => 'Password (again)', 'type' => 'password'));
echo $this->Form->input('first_name');
echo $this->Form->input('last_name');
echo $this->Form->submit('Create account');
echo $this->Form->end();
?>

Here's my action:

public function create() {
    if($this->request->is('post')) {
        $this->User->set($this->request->data);

        $valid = true;
        $validationErrors = array();
        $password = $this->request->data('User.password');
        $password_confirm = $this->request->data('User.password_confirm');

        if(strlen($password) < 5) {
            $validationErrors['password'][] = 'Password must be at least 5 characters long';
            $valid = false;
        }

        if($password != $password_confirm) {
            $validationErrors['password_confirm'][] ='Passwords do not match';
            $valid = false;
        }

        $this->User->data['User']['email'] = $this->request->data('User.soton_username') . '@soton.ac.uk';

        $group = $this->Group->find('first', array('conditions' => array('default' => 1)));
        if($group) {
            $gid = $group['Group']['id'];
        } else {
            $gid = 1;
        }
        $this->User->data['User']['group_id'] = $gid;

        if($this->User->validates() && $valid) {
            $this->User->save();
            $this->Session->setFlash('<a href="/users/activate/' . $this->User->data['User']['activation_id'] . '">Activate</a>');
            return $this->redirect('/users/confirm_create');
        }

        $this->User->validationErrors = array_merge($this->User->validationErrors, $validationErrors);

        if(isset($this->User->validationErrors['email'])) {
            $this->User->validationErrors['soton_username'] = $this->User->validationErrors['email'];
        }

        //debug($this->request->validationErrors);exit;
        $this->Session->setFlash('There were errors with the form.');
    }
}

The soton_username and password_confirm fields are not actually part of the database, but still need to be validated.

My User model does have a $validate variable which Form does recognise as it inserts required="required" in the right places.

Any help would be appreciated.

Upvotes: 6

Views: 2756

Answers (2)

Michael Ozeryansky
Michael Ozeryansky

Reputation: 8053

Here's my answer, since I was not calling User->read():

I dug through cake's core and found that the error fields are auto-populated based on the model name passed with form->create('model').

My model is 'User', and in my view I had $this->form->create('Users'). Notice the 's'. Validation is done on the model, so the validation error array is indexed by the model name: 'User'. The form uses the name passed in create, 'Users', to search for the errors.

To fix this, make sure you use the singular form of the model in form->create(). For me that is 'User'.

Upvotes: 1

james the seventh
james the seventh

Reputation: 228

Ok so I've found the answer to my question.

The following function in my AppController class is the culrprit:

public function beforeRender() {
    $user_id = $this->Auth->user('id');
    $user = $this->User->read(null, $user_id);
    $this->set('user', $user);
}

For some reason, calling the $this->Model->read() function prevents validation errors from being displayed, and this function was being calling this at the end of every action. Moving it to the beforeFilter() function fixes the problem.

Upvotes: 5

Related Questions