I am using CakePHP 2.10.19. I have a form for entering Item Types. I also have other models for entering appropriate database objects. Error I am occurring is that my validation errors are displayed twice for this form. For other forms it works well. Here is the model:
ItemType.php
App::uses('AppModel', 'Model');
class ItemType extends AppModel {
public $classes = array(
'product' => 'Proizvod',
'kit' => 'Kit (bundle)',
'material' => 'Repromaterijal'
);
public $validate = array(
'code' => array(
'required' => array(
'rule' => 'notBlank',
'message' => 'A code is required'
),
'alphanum' => array(
'rule' => 'alphanumeric',
'message' => 'A code must be an alphanumeric value'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'This code already exists!'
),
'between' => array(
'rule' => array('lengthBetween', 3, 7),
'message' => 'Code must be between 3 and 7 characters long'
)
),
'name' => array(
'required' => array(
'rule' => 'notBlank',
'message' => 'A name is required'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'This name already exists!'
),
'between' => array(
'rule' => array('lengthBetween', 3, 30),
'message' => 'Name must be between 3 and 30 characters long'
)
),
'class' => array(
'valid' => array(
'rule' => array('inList', array('product', 'material', 'kit', 'semi_product', 'service_product', 'service_supplier','consumable','inventory','goods','other')),
'message' => 'Please enter a valid class',
'allowEmpty' => false
)
),
'tangible' => array(
'bool' => array(
'rule' => 'boolean',
'message' => 'Incorrect value for the checkbox'
)
),
'active' => array(
'bool' => array(
'rule' => 'boolean',
'message' => 'Incorrect value for the checkbox'
)
)
);
public $hasMany = array(
'Item' => array(
'className' => 'Item',
'foreignKey' => 'item_type_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
ItemTypesController.php
<?php
class ItemTypesController extends AppController {
public function add() {
if ($this->request->is('post')) {
$this->ItemType->set($this->request->data);
if($this->ItemType->validates()){
debug($this->ItemType->validates());
$this->ItemType->create();
if ($this->ItemType->save($this->request->data)) {
$this->Flash->success(__('The item type has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
debug($this->ItemType->invalidFields());
$this->Flash->error(__('The item type could not be saved. Please, try again.'));
}
}
debug($this->ItemType->invalidFields());
$this->Flash->warning($this->ItemType->validationErrors, array(
'key' => 'negative'
));
}
$this->set('classes', $this->ItemType->classes);
}
}
Also, debug($this->ItemType->invalidFields()) is showing array with two fields for each field, like this:
array(
'code' => array(
(int) 0 => 'Code must be between 3 and 7 characters long',
(int) 1 => 'Code must be between 3 and 7 characters long'
),
'name' => array(
(int) 0 => 'Name must be between 3 and 30 characters long',
(int) 1 => 'Name must be between 3 and 30 characters long'
)
)
...so I am guessing a model is making some sort of mistake.
add.ctp
<div class="itemTypes form">
<?php echo $this->Form->create('ItemType'); ?>
<fieldset>
<legend><?php echo __('Add Item Type'); ?></legend>
<?php
echo $this->Form->input('code');
echo $this->Form->input('name');
echo $this->Form->input('class', array('options' => $classes));
echo $this->Form->input('tangible');
echo $this->Form->input('active');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
Anyone has an idea. Thing is, other controllers have basically the same logic but do not have this sort of a mistake where validation errors are displayed twice.
Generally this is because validation is triggered twice. This is triggered twice, once when you call $this->ItemType->validates()) and another time when you call debug($this->ItemType->invalidFields());
Please comment and remove all the debug statements.
Apparently upon removing the debug statements it works like it should with only one validation error per type as it should do. Not sure why debug made problem tho.
Related
I am working on cakephp v2.3. While I am validation data by $this->User->validates it will always return false even if values are there.
Here is my validation rule
public $validate = array(
'first_name' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.',
'last' => true,
'required' => true,
),
'size' => array(
'rule' => array('maxLength', 50),
'message' => 'This field must be no larger than 50 characters long.'
),
),
'last_name' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.',
'last' => true,
'required' => true,
),
'size' => array(
'rule' => array('maxLength', 50),
'message' => 'This field must be no larger than 50 characters long.',
'allowEmpty' => true,
),
),
'email' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.',
'last' => true,
'required' => true,
),
'checkMail' => array(
'rule' => 'checkMail',
'message' => 'Please provide a valid email address.',
'last' => true,
),
'isUnique' => array(
'rule' => 'isUnique',
'message' => 'Email address already in use.',
'last' => true,
),
),
'password' => array(
'rule1' => array(
'rule' => array('minLength', 6),
'message' => 'Passwords must be at least 6 characters long.',
'required' => true,
),
),
'verify_password' => array(
'rule' => 'validIdentical',
),
'current_pass' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.',
'last' => true,
),
'match' => array(
'rule' => 'validICurrent',
)
),
'gender' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.',
'last' => true,
),
),
'mobile' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.',
'last' => true,
'required' => true,
),
'numeric' => array(
'rule' => 'numeric',
'message' => 'Please enter valid phone numbers.',
)
),
'image' => array(
'SizeLimit' => array(
'rule' => array('isUnderPhpSizeLimit', false),
'message' => 'File exceeds upload filesize limit',
),
'FormSizeLimit' => array(
'rule' => array('isUnderFormSizeLimit', false),
'allowEmpty' => true,
'message' => 'File exceeds form upload filesize limit'
),
'CompletedUpload' => array(
'rule' => array('isCompletedUpload', false),
'message' => 'File was not successfully uploaded'
),
'ValidExtension' => array(
'allowEmpty' => true,
'rule' => array('isValidExtension', array('gif', 'png', 'jpg', 'jpeg'), false),
'message' => 'File does not have a gif, png, ,jpg and jpeg extension'
)
),
);
and this is how I am validating
if ($this->request->is("post")) {
if (!empty($this->request->data)) {
if (!$this->User->validates($this->request->data)) {
$this->Session->setFlash(__('The Information could not be saved. Please, try again.'), 'message', array('class' => 'danger'));
$this->redirect(Router::url('/', true) . 'sign-up/');
}
}
When I try
die(debug($this->User->invalidFields()));
it will return
array(
'password' => '*****',
'last_name' => array(
(int) 0 => 'This field cannot be left blank.',
(int) 1 => 'This field cannot be left blank.'
),
'email' => array(
(int) 0 => 'This field cannot be left blank.',
(int) 1 => 'This field cannot be left blank.'
),
'mobile' => array(
(int) 0 => 'This field cannot be left blank.',
(int) 1 => 'This field cannot be left blank.'
)
)
This is the data I am passing
Array
(
[User] => Array
(
[role_id] => 2
[first_name] => kapil
[last_name] => sharma
[email] => kapiltest#mailinator.com
[password] => abc#123
[verify_password] => abc#123
[mobile] => 1234567890
[gender] => Male
[image] => Array
(
[name] => Screenshot_61.png
[type] => image/png
[tmp_name] => /tmp/phppYBJQF
[error] => 0
[size] => 50611
)
)
)
Your Validations seems fine to me But if we don't set the data in model some time that will cause this kind of issue.
Add below line before validating.
$this->User->set($this->request->data);
So code should look like
$this->User->set($this->request->data); //set data in model
if (!$this->User->validates()) {
$this->Session->setFlash(__('The Information could not be saved. Please, try again.'), 'message', array('class' => 'danger'));
$this->redirect(Router::url('/', true) . 'sign-up/');
}
Insde the User Model
App::uses('SimplePasswordHasher','Controller/Component/Auth');
class User extends AppModel {
public $useTable = 'users';
public $hasMany = array(
'Reminder' => array(
'className' => 'Reminder'
)
);
public $validate = array(
'username' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
'between' => array(
'rule' => array('between',5,15),
'message' => 'Between 5 to 15 characters'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Username is already taken'
)
),
'password' => array(
'between' => array(
'rule' => array('between',5,10),
'message' => 'Between 5 to 10',
),
'compareFields' => array(
'rule' => array('compareFields','confirm_password'),
'message' => 'Passwords do not match',
'required' => 'update'
)
),
'email' => array(
'email' => array(
'rule' => 'email',
'message' => 'Please enter valid email address'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Email is already in use'
),
'compareFields' => array(
'rule' => array('compareFields','confirm_email'),
'message' => 'Emails do not match',
'required' => 'update'
)
),
'timezone' => array(
'isValid' => array(
'rule' => 'isValid',
'message' => 'Please select a timezone'
)
)
);
Inside the User Controller.
// Changed existing emails
if(!empty($this->request->data['User']['email'])) {
echo "Email is set <br/>";
$this->User->set($this->request->data['User']['email']);
if($this->User->validates(array('fieldList' => array('email')))) {
echo "Email is valid <br/>";
$this->User->id = $this->Session->read('Auth.User.id');
$this->User->saveField('email',$this->request->data['User']['email'],true);
$this->Session->setFlash("Settings updated");
}
}
// Change existing password
if(!empty($this->request->data['User']['password'])) {
echo "Password is set <br/>";
$this->User->set($this->request->data['User']['password']);
if($this->User->validates(array('fieldList' => array('password')))) {
echo "Password is valid <br/>";
$this->User->id = $this->Session->read('Auth.User.id');
$this->User->saveField('password', $this->request->data['User']['password'],true);
$this->Session->setFlash("Password changed");
}
}
I know 'saveField()' doesn't do validation automatically so I've set the validation parameter to true, but to no avail.
I've included the models containing the validations.
Any help would be appreciated.
Edited:
I actually ment that you had to do the validation like this:
$this->User->id = $this->Session->read('Auth.User.id');
if(!$this->User->saveField('password', 'asdf', true)) {
echo "Invalid.";
pr($this->User->invalidFields());
} else {
echo "Saved!";
}
or optionally, do this:
Just read() the data, overwrite the new password in that array, then $this->User->set() and use $this->User->validates() like you have.
See here.
I followed this post for password confirmation, but CakePHP seems to be skipping over my re_password validation settings.
Here's my form
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend><?php echo __('Add Account'); ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->input('re_password', array('type'=>'password', 'label'=>'Re-Enter Password', 'value'=>''));
echo $this->Form->input('role', array('type' => 'hidden', 'default' => 'user'));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
This is in my User model
function equalToField($array, $field) {
return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('minLength', '3'),
'message' => 'A username with a minimum length of 3 characters is required'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'This username has already been taken.'
)
),
'email' => array(
'email' => array(
'rule' => array('email'),
'message' => 'Please enter a valid email address.',
)
),
'password' => array(
'required' => array(
'rule' => array('minLength', '8'),
'message' => 'A password with a minimum length of 8 characters is required'
)
),
're_password' => array(
'required' => array(
'rule' => array('equalToField', 'password'),
'message' => 'Passwords do not match'
)
)
);
An error occurs if the minlength rule was triggered for the password field, but nothing ocurrs for the re_password field
I deleted the equalToField method just to see what would happen. I didn't even get an error so it seems as if re_password isn't even being looked at.
I'm not sure if this has anything to do with it, but when I added an additional rule to the password field regarding re_password, I got the following error: "Undefined index: re_password [APP/Model/User.php"
'password' => array(
'required' => array(
'rule' => array('minLength', '8'),
'rule' => array('equalToField', 're_password'),
'message' => 'A password with a minimum length of 8 characters is required'
)
),
Also, in my UsersController action I printed(this->request->data) and the re_password field is set.
For CakePHP2 you can use something like this:
public $validate = array(
'password' => array(
'length' => array(
'rule' => array('minLength', '8'),
'message' => 'Password should have at least 8 chars.'
)
),
'password_confirmation' => array(
'length' => array(
'rule' => array('minLength', '8'),
'message' => 'Password should have at least 8 chars.'
),
'compare' => array(
'rule' => array('validate_passwords'),
'message' => 'Passwords are not same.',
)
),
);
public function validate_passwords() {
return $this->data[$this->alias]['password'] === $this->data[$this->alias]['password_confirmation'];
}
This is working for me, Try with this..
public $validate = array(
'password' => array(
'minLength' => array(
'rule' => array('minLength', 4),
'message' => 'Password must be at least 4 characters long'
),
'maxLength' => array(
'rule' => array('maxLength', 50),
'message' => 'Password cannot be longer than 50 characters'
),
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'Please enter a password'
)
),
'confirm_password' => array(
'passwordMatch' => array(
'rule' => array('identicalFieldValues', 'password'),
'message' => 'The two passwords you entered do not match, please try again'
),
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'Please confirm your password by entering it twice'
)
)
);
I am Trying to validate data from Form(.ctp file) in cakephp 2.3.8.
echo $this->Form->create('User').'<br />'.
$this->Form->input('handle', array(
'rule' => 'notEmpty',
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Username must be only letters and numbers, no special characters'
),
'between' => array(
'rule' => array('between', 4, 8),
'message' => 'Username must be between 4 and 8 characters',
),
'isUnique' => array(
'rule' => 'isUnique',
'message' => 'This username is already taken. Please choose a different one.'
))).'<br />'.
$this->Form->input('email',array(
'type'=>'text',
'placeholder'=>'Enter your E-mail',
'class'=>'form-control')).'<br />'.
$this->Form->input('password',array(
'type'=>'password',
'placeholder'=>'Enter your password',
'class'=>'form-control'));?>
This is my modle code
public function beforeSave($options = array()) {
parent::beforeSave($options = array());
if (isset($this->data['User']['password'])) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
$this->data['User']['token'] = Security::hash(mt_rand(),'md5',true);
$this->data['User']['resetkey'] = Security::hash(mt_rand(),'md5',true);
return true;
}
but when i singup, it not validating data and i don't know where i am mistaking
I have not seen validation rules in the view before, only in either the model or the controller. This may very well be an alternate method. Try moving validation code to the model.
class User extends AppModel {
public $validate = array(
'handle' => array(
'lengthCheck'=>array(
'rule'=>array('between', 4, 8),
'message'=>'The username must be between 4 and 8 characters.'
),
'isUnique'=>array(
'rule'=>'isUnique',
'message'=>'This username is already taken. Please choose a different one.'
),
'alphanumeric' => array(
'rule' => array('alphanumeric'),
'message' => 'Username must be only letters and numbers, no special characters',
),
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Please enter your username',
),
),
'password' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Please enter your password',
),
),
'email' => array(
'email' => array(
'rule' => array('email'),
'message' => 'Invalid email',
),
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Please enter your email',
),
),
);
In your view
<?php
echo $this->Form->create('User');
echo $this->Form->input('handle', array(
'placeholder'=>'Enter your username',
'class'=>'form-control'
));
echo $this->Form->input('email', array(
'placeholder'=>'Enter your E-mail',
'class'=>'form-control'
));
echo $this->Form->input('password', array(
'placeholder'=>'Enter your password',
'class'=>'form-control'
));
?>
By default, it will recognize the password field as 'type' => 'password'
I'm trying to find out how to get the actual message from my validate() array which contains all the rules to validate a submission within my model.
Basically I'm POSTing ajaxily and I'd like to return all of the error messages in the form that have failed validation, but it's sending them anyway even when they have passed validation.
So in my
SubmissionsController I'm doing this:
if ($this->request->is('ajax')) {
$formData = $this->Submission->invalidFields();
$this->set(compact('formData'));
}
In my Submission model I have:
var $validate = array(
'title' => array(
'title' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please enter a title'
),
'minLength' => array(
'rule' => array('minLength', 5),
'message' => 'Please make your title longer (e.g. IJL John F. Kennedy donated his presidential salary to charity)'
),
'maxLength' => array(
'rule' => array('maxLength', 300),
'message' => 'Your title needs to be shorter'
),
),
'description' => array(
'shortDescription' => array(
'rule' => array('shortDescription'),
'message' => 'Your description needs to be longer'
),
'longDescription' => array(
'rule' => array('longDescription'),
'message' => 'Your description needs to be shorter'
),
),
'source' => array(
'source' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
'website' => array(
'rule' => 'url',
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
),
'category' => array(
'category' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please choose a category'
)
)
);
In my Submissions/json/submit.ctp file I have:
<?php
$fragment = $this->element('errors/flash_error');
$toReturn = array(
'formData' => $formData
);
echo json_encode($toReturn);
If I enter in a valid title or any other valid field, I still am getting back the error message instead of nothing.
Is there something I'm missing that invalidFields() needs in order to NOT return fields which HAVE passed validation?
EDIT:
As Leo suggested below, I wasn't calling save before invalidFields()
The correct code should be:
if ($this->Submission->save($this->request->data)) {
$formData = null;
} else {
$formData = $this->Submission->invalidFields();
}
$this->set(compact('formData'));
You're calling invalidFields() without validation either by a save() call or validates()!