Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cakephp validation from both model and controller

Tags:

cakephp

I have given validation in model. Also, I have given some validation in controller for checking the captcha code. After that, the application is not displaying the model validation errors. If I comment the controller code, model validation is working fine and displaying the errors. Both not working..

Model code (sample)

class User extends AppModel {

var $name = 'User';

var $validate = array(
    'username' => 'notempty',
    'firstname' => 'notempty'
    );

}

Controller code

if (!empty($this->data)) {

$this->User->set($this->data);
$this->User->create();
$captcha = $this->Session->read('CAPTCHA_CODE');

if (strtolower($captcha) != strtolower($this->data['User']['captcha']))
{
    $this->User->invalidate('captcha', __('Sorry, your entry did not match', true));
}

if ($this->User->save($this->data, array('validate' => 'only')))
{
    if ($this->User->save($this->data, array('validate' => 'false'))) {
        $this->Session->setFlash(__('Registered successfully', true));
        $this->redirect('success');
    }
}else {
    $this->Session->setFlash(__('Please, try again.', true));
}

}

I have replaced the if ($this->User->save($this->data, array('validate' => 'only'))) line with if ($this->User->validates()), then also it is not working.

please help

like image 252
binoy Avatar asked Mar 24 '10 13:03

binoy


1 Answers

Your code should work with if ( $this->User->validates() ). The incorrect behaviour you're having trouble with is because Model::save() resets the Model::validationErrors member, obliterating your custom validation error. Model::validates() doesn't, so your dual-validation setup should work.

For example, the following functions correctly, under CakePHP 1.2.

Model:

class User extends AppModel
{
    var $validate = array(
        'my_other_field' => array(
            'rule' => 'notEmpty',
            'message' => 'This field should not be empty.'
        )
    );
}

Controller:

class UsersController extends AppModel
{
    function add()
    {
        if (! empty($this->data)) {
            $this->User->set( $this->data );

            if ( 'foo' != $this->data['User']['my_field'] ) {
                $this->User->invalidate( 'my_field', 'Should be "foo".' );
            }

            if ( $this->User->validates() ) {
                $this->flash('Form validated correctly.'); exit;
            }
        }
    }
}

View:

<?php echo $form->create('User', array('action'=>'add')); ?> 
<?php echo $form->input('User.my_field', array('value'=>'bar')); ?> 
<?php echo $form->input('User.my_other_field', array('value'=>'')); ?> 
<?php echo $form->end('Submit'); ?> 

Submitted as-is above, form validation errors appear below both fields, one provided from the controller's validation logic, the other from the model's validation rules.

The larger issue, of course, is muddying the MVC roles by having the controller handling some data validation. You might want to consider something like this:

Controller:

class UsersController extends AppController
{
    function add()
    {
        if (! empty($this->data)) {

            $captcha = $this->Session->read('CAPTCHA_CODE');
            $this->User->setCaptchaCheck( $captcha );

            if ( $this->User->save( $this->data, array('validate'=>true))) {
                $this->Session->setFlash('Success');
                $this->redirect('success',303,true);
            }
        }
    }
}

Model:

class User extends AppModel
{
    var $captchaCheck = '';

    var $validates = array(
        'captcha' => array(
            'matchesCheck' => array(
                'rule' => array( 'matchesCaptchaCheck', 'captchaCheck' ), // second value of array should match class member-name above
                'message' => "CAPTCHAs don't match."
            )
        )
    );

    function matchesCaptchaCheck( $data, $checkVar )
    {
        $data = reset(array_values($data)); // I don't need to know the field name now.

        return low($data) == low($this->{$checkVar});
    }

    function setCaptchaCheck( $captcha )
    {
        $this->captchaCheck = $captcha;
    }
}

Now your controller is blissfully ignorant of how your model validates its data, and even of how the data is structured; and your form validation all occurs in the model.

Hope this helps.

like image 63
Daniel Wright Avatar answered Sep 30 '22 00:09

Daniel Wright