0

I am working in CakePHP 3.2. I have users table and register action in UsersController.

I'm trying to add a new record but default validation is not working.

This is my 'UsersTable.php`

<?php
namespace App\Model\Table;

use App\Model\Entity\User;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Validation\Validator;

class UsersTable extends Table
{

    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('users');
        $this->displayField('name');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');

        $this->hasMany('UserAddresses', [
            'foreignKey' => 'user_id'
        ]);
    }

    /**
     * Default validation rules.
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */
    public function validationDefault(Validator $validator)
    {
        $validator
            ->uuid('id')
            ->allowEmpty('id', 'create');

        $validator
            ->notEmpty('name');

        $validator
            ->email('email')
            ->notEmpty('email');

        $validator
            ->add('mobile', [
              'minLength' => [
                'rule' => ['minLength', 10],
                'message' => 'Mobile number must be of 10 characters long',
              ],
              'maxLength' => [
                'rule' => ['maxLength', 10],
                'message' => 'Mobile number must be of 10 characters long',
              ]
            ])
            ->numeric('mobile')
            ->notEmpty('mobile');

        $validator
            ->notEmpty('password');

        $validator
            ->add('newPassword', [
              'compare' => [
                'rule' => ['compareWith', 'confirmNewPassword'],
              ]
            ])
            ->notEmpty('newPassword');
        $validator
            ->add('confirmNewPassword', [
              'compare' => [
                'rule' => ['compareWith', 'newPassword'],
                'message' => 'Password does not match'
              ]
            ])
            ->notEmpty('confirmNewPassword');

        return $validator;
    }

    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->isUnique(['email']));
        return $rules;
    }

    public function validationPassword(Validator $validator)
    {
        $validator
            ->add('old_password', 'custom', [
              'rule' => function($value, $context){
                $user = $this->get($context['data']['id']);
                if ($user) {
                  if((new DefaultPasswordHasher)->check($value, $user->password)) {
                    return true;
                  }
                }
                return false;
              },
              'message' => 'The old password does not match the current password!',
            ])
            ->notEmpty('old_password');

        $validator
            ->add('password1', [
              'length' => [
                'rule' => ['minLength', 6],
                'message' => 'The Password have to be at least 6 characters!',
              ]
            ])
            ->add('password1', [
              'match' => [
                'rule' => ['compareWith', 'password2'],
                'message' => 'The passwords does not match!',
              ]
            ])
            ->notEmpty('password1');

        $validator
            ->add('password2', [
              'length' => [
                'rule' => ['minLength', 6],
                'message' => 'The Password have to be at least 6 characters!',
              ]
            ])
            ->add('password2', [
              'match' => [
                'rule' => ['compareWith', 'password1'],
                'message' => 'The passwords does not match!',
              ]
            ])
            ->notEmpty('password2');

        return $validator;
    }
}

register() method

public function register()
    {
        // if already logged in, redirect to referer action to prevent new registration
        if (!empty($this->Auth->user('id'))) {
          return $this->redirect($this->referer());
        }

        $user = $this->Users->newEntity();
        if ($this->request->is('post')) {
          // check user exists or not
          $userExists = $this->Users->find('all', [
            'conditions' => [
              'OR' => [
                'email' => $this->request->data['email'],
                'mobile' => $this->request->data['mobile'],
              ]
            ]
          ]);
          if ($userExists->count() > 0) {
            $userExists = $userExists->first();
            $this->Flash->success(__('It seems you are already registered. Please login using your email or mobile and passowrd'));
            return $this->redirect(['controller' => 'Users', 'action' => 'login']);
          }

            $hash = hash('sha256',date('YmdHis').time());
            $user->tmp_hash = $hash;
            $user->verified = 0;
            $user = $this->Users->patchEntity($user, $this->request->data);
            if ($u = $this->Users->save($user)) {
              // send verification email
              if ($this->sendEmail($user->id, $user->email, $hash, 'register')) {
                $this->Flash->registerSuccess(__('Thank you. You need to verify email. Not received verification email ?'), [
                  'params' => [
                    'userId' => $user->id
                  ],
                  ['escape' => false]
                ]);
                return $this->redirect(['action' => 'login']);
              } else {
                $this->Flash->error(__('The user could not be saved. Please, try again.'));
                return $this->redirect(['action' => 'login']);
              }
            }
        }
        $this->set(compact('user'));
        $this->set('_serialize', ['user']);
    }

register.ctp view

<?= $this->Form->create(null, ['url' => ['controller' => 'Users', 'action' => 'register'], 'class' => 'regForm']) ?>
            <div class="form-group">
              <label>Name <?= $this->Form->error('name') ?></label>
              <?= $this->Form->input('name', ['class' => 'form-control', 'label' => false, 'placeholder' => 'Enter Your Name', 'title' => 'Please Enter your full name']) ?>
            </div>
            <div class="form-group">
              <label>Email address</label>
              <?= $this->Form->input('email', ['label' => false, 'class' => 'form-control', 'placeholder' => 'Enter Email', 'title' => 'Please enter valid email']) ?>
            </div>
            <div class="form-group">
              <label>Mobile</label>
              <?= $this->Form->input('mobile', ['label' => false, 'class' => 'form-control', 'placeholder' => 'Mobile Number', 'title' => 'Please enter valid mobile no to receive notifications']) ?>
            </div>
            <div class="form-group">
              <label>Password</label>
              <?= $this->Form->input('password', ['label' => false, 'class' => 'form-control', 'placeholder' => 'Password', 'title' => 'Please enter password']) ?>
            </div>
            <?= $this->Form->button('<i class="fa fa-user"></i> Create and account', ['type' => 'submit', 'class' => 'btn btn-primary', 'escape' => false]) ?>
            <?= $this->Form->end() ?>
        </div>

When I try to submit form without filling anything, it simply refreshes the form without showing validation error.

Anuj TBE
  • 9,198
  • 27
  • 136
  • 285
  • Where are you checking validation in controller? – Pradeep Singh Jul 20 '16 at 09:33
  • I'm not checking validation in controller. I mean to say that as given in `usersTable` validation for name to notEmpty. But when I submit the form without filling name field. It is not validated and rest of the form data is submitted into database. instead of showing error as `This field cannot be empty` – Anuj TBE Jul 20 '16 at 09:38
  • May be this is bcoz of `$this->Form->create(null` ,Try putting model name – Pradeep Singh Jul 20 '16 at 09:46
  • actually there are two forms on the same page. One for `login` and other for `register` both are for different actions `login` and `register` respectively. – Anuj TBE Jul 20 '16 at 09:49
  • thanks it works but isn't there any way to do it with some other action form in view of another action – Anuj TBE Jul 20 '16 at 09:56

1 Answers1

2

In your register.ctp file

$this->Form->create(null, ['url' => ['controller' => 'Users', 'action' => 'register'], 'class' => 'regForm']);

Replace it with

$this->Form->create($user, ['url' => ['controller' => 'Users', 'action' => 'register'], 'class' => 'regForm']);

As per concept of CakePHP v3 you have to pass entity in Form Creation method so it will display form validation error in view.

Haresh Vidja
  • 8,340
  • 3
  • 25
  • 42
  • adding line `$this->Form->create($user, ['url' => ['controller' => 'Users', 'action' => 'register'], 'class' => 'regForm']);` on `login.ctp` view of `login` action gives error `undefined variable user` – Anuj TBE Jul 20 '16 at 11:57
  • Have you create new entity of user and pass it in view in login method code on crontroller? $user = $this->Users->newEntity(); /// your logic here $this->set(compact('user')); – Haresh Vidja Jul 20 '16 at 11:59
  • do I need to create new entity on login action even if registration will be processed by `register()` action – Anuj TBE Jul 20 '16 at 12:02
  • 1
    If Register and Login form in same ctp file then no need to create new entity.. If you dont want to create new entity, you can pass Entity name only instead of variable, $this->Form->create('user', ..........); – Haresh Vidja Jul 20 '16 at 12:27