CakePHP Validation depending on other field - cakephp

I wonder if it is possible with CakePHP validation rules to validate a field depending on another.
I have been reading the documentation about custom validation rules but the $check param only contains the value of the current field to validate.
For example. I would like to define the verify_password field as required only if the new_password field is not empty. (in case
I could do it with Javascript anyway but i wonder if it is possible to do it directly with CakePHP.

When you validate data on a model, the data is already set(). This means that you can access it on the model's $data property. The example below checks the field we're validating to make sure it's the same as some other field defined in the validation rules (such as a password confirm field).
The validation rule would look something like this:
var $validate = array(
'password' => array(
'minLength' => array(
'rule' => array('minLength', 6),
'message' => 'Your password must be at least 6 characters long.'
),
'notempty' => array(
'rule' => 'notEmpty',
'message' => 'Please fill in the required field.'
)
),
'confirm_password' => array(
'identical' => array(
'rule' => array('identicalFieldValues', 'password'),
'message' => 'Password confirmation does not match password.'
)
)
);
Our validation function then looks at the passed field's data (confirm_password) and compares it against he one we defined in the rule (passed to $compareFiled).
function identicalFieldValues(&$data, $compareField) {
// $data array is passed using the form field name as the key
// so let's just get the field name to compare
$value = array_values($data);
$comparewithvalue = $value[0];
return ($this->data[$this->name][$compareField] == $comparewithvalue);
}
This is a simple example, but you could do anything you want with $this->data.
The example in your post might look something like this:
function requireNotEmpty(&$data, $shouldNotBeEmpty) {
return !empty($this->data[$this->name][$shouldNotBeEmpty]);
}
And the rule:
var $validate = array(
'verify_password' => array(
'rule' => array('requireNotEmpty', 'password')
)
);

Related

Cakephp Model Rule

I read from the cakePhp documentation , they only allow one rule per field.
However If my field require unique Date and must be date format. How should I place them ?
Current Code
<?php
App::uses('AppModel', 'Model');
class EventDate extends AppModel {
//public $useTable = 'eventdate';
public $primaryKey = 'event_date_id'; //I still need for Delete
public $validate = array(
'event_date' => array(
'rule' => array('date','ymd'),
'message' => 'Enter a valid date in YY-MM-DD format.',
'required' => true,
'allowEmpty' => false
)
// ,'event_date' => array(
// 'rule' => 'isUnique'
// )
);
}
There is no restriction on the number of rules a field can have in CakePHP. You can provide an associative array of rules for a specific field like this:-
public $validate = array(
'event_date' => array(
'format' => array(
'rule' => array('date','ymd'),
'message' => 'Enter a valid date in YY-MM-DD format.',
'required' => true,
'allowEmpty' => false
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'This date already exists'
)
)
);
Just remember to make sure your array indexes are unique.
The array indexes for the individual rules (e.g. format and unique in the example code) can be anything, but make them descriptive to the rule being defined.

MultivalidatableBehavior with cakephp 2.3.0. Not Working

I am using 'MultivalidatableBehavior' in cakephp. Though it worked fine with previous version. But its not working with Cakephp 2.4.0 version. Is their any changes with this behaviour. Because When I use this code.
var $validationSets = array( 'ruleset mentioned in it. ');
Though my request go through the Behaviour class but its not putting validation on the desired field. I have also checked $this->request->data Its also valid and for same Model where ruleset has been written.
I tried to debug using die in my MultivalidatableBehavior class. Though during valiation my request falls in the function of setValidation(&$model, $rules = array()) {. Please suggest if it is compatible with greater version of cakephp2.3.
My tried code..
Model Code :
var $actsAs = array('Multivalidatable');
var $validationSets = array(
'login' => array(
'username' => array('required' => array('rule' => array('notEmpty'), 'message' => 'Username is required !!')),
'password' => array('required' => array('rule' => array('notEmpty'), 'message' => 'Password is required !!')),
),
);
Controller Call.
$this->User->setValidation('login'); Fields are also with same name.
Its not validating If I put if($this->User->setValidation('login')) it returns false.
Thanks to Piotr Beschel for helping me out. I shouldn't use any sort of behaviour. It can also be achieved without behaviour. My Model code would be
public $validationAdmin = array(
'adminLogin' => array(
'username' => array('required' => array('rule' => array('notEmpty'), 'message' => 'Please enter your username !!')),
'password' => array('required' => array('rule' => array('notEmpty'), 'message' => 'Please enter your password !!')),
),
'adminForgotPassword' => array(
'email' => array('required' => array('rule' => array('notEmpty'), 'message' => 'Please enter your email address !!'),
'email' => array('rule' => array('email'), 'message' => 'Please enter valid mail address')),
),
);
That is simply creating variable named $valdiationAdmin I have named it as admin to know following rule set is for admin.
My sample controller code would be.
$this->Admin->validate = $this->Admin->validationAdmin['adminLogin'];
Just this way. If form has data to save it would move like butter. In case data is just validating I have to force form to validate it(In case login where data is not saved).
if ($this->Admin->validates()) {
} else {
$errors = $this->Admin->validationErrors;
$this->set('validationErrors', $errors);
}
It would validate my form. Even add error message to form field in ctp file. I need not to write $this->form->error('fieldname');
Thanks again to all the viewer. Suggest me something if more better. I am thinking to validate data of other form if associated with one form, with same implementation. Help if you can.
The method
$this->User->setValidation('login')
only chooses which validation Set will be used.
Use:
if ($this->User->validates()) {
...
to get the result of the validation.

Cakephp makes a unique key validation that I did not ask for

I have a simple table where one of the field is country
It is not defined as unique key in the database and when I try to insert a record with the same country directly in MySql , the record is inserted without error. Fine.
But when I tried to insert through a edit screen in my Cakephp application, I got the error message on the country field 'Alphanumeric' which does not correspond to the reality because if I enter
for example: United States which is a country of another existing record, I got the error, if I enter xxxxx, the system accept to save the record. THat's is why I suspect that there is a check on unique Key.
My model for this field is the following
'country' => array(
'notempty' => array(
'rule' => array('notempty'),
),
'alphanumeric' => array(
'rule' => array('alphanumeric'),
),
)
Do you have any idea ? Is there another place where I should check ?
"United States" contains a space. The alphanumeric rule won't validate strings with space.
**Use this code for unique validation form in cakephp.........**
$validator = $this->validator();
$validator['username'] = array(
'unique' => array(
'rule' => 'isUnique',
'required' => 'create'
),
'alphanumeric' => array(
'rule' => 'alphanumeric'
)
);

Unique rule is applied when editting a record in CakePHP

Here is the validation rule:
'name'=>array(
'Please enter customer\'s name'=>array(
'rule'=>'notEmpty',
'message'=>'Please enter customer\'s name'
),
'Unique' => array(
'rule' => array('nameIsUniqueForCompany'),
'message' => 'Customer with these initials already exists'
)
),
public function initialsAreUniqueForCompany($data){
$company_id = $this->data['Customer']['company_id'];
$initials = $this->data['Customer']['initials'];
if($this->find('first', array('conditions'=>array('initials'=>$initials, 'company_id'=>$company_id))))
{
return false;
}
return true;
}
The problem is that the rule is applied to a current object. Let's say I want to update a customer named 'ABC', but I just change his phone number. The application will then look if the name ABC already exists and it will ofcourse find it and will not update.
any ideas?
Your implementation is flawed:
By design your validation rule will always only work for add, not for edit.
On edit, you need to also take the current ID into consideration.
Check out my http://www.dereuromark.de/2011/10/07/maximum-power-for-your-validation-rules/ post. The part about uniqueness contains a working approach.
For you that means, using my enhanced unique validation method:
'name' => array(
'validate' => array(
'rule' => array('validateUnique', array('company_id')),
'message' => 'Customer with these initials already exists',
),
),
Basically, you always submit the id on edit (via hidden form field - automatically done by baked forms anyway), and remove it from the find result by using "id != current" in your conditions:
$this->alias . '.id !=' => $id
Reasoning: The currently edited record should not trigger the validation rule error, of course :)
You can pass something like this:
'email' => array(
'unique' => array(
'rule' => 'isUnique',
'message'=>'This e-mail has been used already',
'on'=>'create'
)
)
There is a node 'on'=>'create' in the array, which apply the rule only when the record has been created. Ofcourse there is also 'on'=>'update' and this will apply when the record is updated.
For update validation you should consider custom rule where you are checking row id to be different.
In your controller
public function edit($id = null) {
if ($this->request->isPut() || $this->request->isPost()) {
if ($this->YourModel->save()){
// do what ever you want
}
} else {
$this->request->data = $this->YourModel->read(null, $id)
}
}
and in your edit.ctp file
echo $this->Form->create('YourModel');
echo $this->Form->hidden('id');
please let me know if you found any problem, glad to help you.
you can try
'subscription_name' => array
(
'required'=>true,
'rule' => 'notEmpty',
'message' => 'Please enter Package name.',
'Unique'=>array(
'rule' => 'isUnique',
'message'=>'package name is already exit..'
)
),

cakePHP "required" validation

is there any mistake in this validation???
var $validate = array(
'brand_id' => array(
'required' => array(true),
'message' => array('select a brand'),
)
);
brand_id is a select box
It show error as "message" instead of "select a brand"
if the message is not in array it shows error
Warning (2): preg_match() [function.preg-match]: Delimiter must not be alphanumeric or backslash [CORE\cake\libs\model\model.php, line 2571]
using cakePHP 1.3
You're missing a rule, just required won't do. Use 'notEmpty' as rule if that's what you want. Also, required and message should (must?) not be arrays.
Why do you have arrays everywhere?
var $validate = array(
'brand_id' => array(
'required' => true,
'message' => 'select a brand',
)
);
Refer to:
http://book.cakephp.org/1.3/en/The-Manual/Common-Tasks-With-CakePHP/Data-Validation.html

Resources