CakePHP Validation nonBlank fails Whether the Field is Empty or !Empty - validation

The docs say that 'notBlank' is a validation rule for fields that you want to make sure they are not empty, as in !empty($somevalue), but when I leave the field blank ('') or when I put a value in the field ('s0meCraZyPasSworD') it still display the error message?
Can anyone see what I'm doing wrong? The rest of the validations work like minlength, but I commented them out to get a better idea of why 'notBlank' doesn't appear to be working...
CONTROLLER:
// Set of validation rules to be run
$validateRules = [
'fieldList' => [
'currentpassword',
'newpassword',
'confirmpassword'
]
];
if ($this->Admin->validates( $validateRules )) {
...
}
MODEL:
class Admin extends AppModel
{
public $name = 'Admin';
public $validate = [
'currentpassword' => [
'notBlank' => [
'rule' => 'notBlank',
'message' => 'Current password is required.'
]
],
...

You tagged CakePHP 2.4 - notBlank was added in 2.7 so you have to use notEmpty or set allowEmpty to false...

The data sent to the model’s save() method must contain data for the
login field. If it doesn’t, validation will fail. The default value
for this key is boolean false.
required => true does not mean the same as the validation rule
notBlank(). required => true indicates that the array key must be
present - it does not mean it must have a value
From the official website:
http://book.cakephp.org/2.0/en/models/data-validation.html#required
So you will need another rule like the allowEmpty to validate this field and not the notBlank rule.

Related

FormRequest messages() function does not translate all rules [duplicate]

I'm working on a Laravel 5.8 project and trying to show custom validation messages for a validation which uses the requiredIf validation rule.
Here is how I have it set up:
$validation = Validator::make(
$request->all(),
[
...
'sum' => [
Rule::requiredIf(function() use ($request){
$model = Model::find($request->id);
return $model->is_special; //returns a boolean value
}),
'numeric'
],
...
],
[
...
'sum.required_if' => 'This cannot be blank',
'sum.numeric' => 'Must use a number here',
...
]
);
Now the validation is working correctly and the custom message for the numeric validation shows as should, but the message I get for the requiredIf() method is Laravel's default error message.
I also tried using 'sum.requiredIf' => '...' but that didn't work either and can't seem to find any documentation or example for this scenario.
I was tinkering with this for a while and noticed that for this to work I needed to define
'sum.required' => 'This cannot be blank'
and not 'sum.required_if' => 'This cannot be blank',.
Not sure if this is expected behavior or just a workaround but my deduction is that with the callback Rule::requiredIf(function() use ($request){...}) the parameters :other and :value are not passed so it falls back onto required messaging and I guess this makes sense since required_if and required would not be used on the same :attribute.
Hope this helps anyone who comes across this problem.
First, create a rule name isSpecial or whatever
php artisan make:rule isSpecial
Go to App\Rules\isSpecial.php
private $id;
public function __construct($id) // pass id or what you need
{
//
$this->id=$id;
}
public function passes($attribute, $value) // customize your rules here
{
//
return Model::find($request->id)->is_special;
}
public function message() // here is answer for your question
{
return 'The validation error message.'; // your message
}
in your controller
use App\Rules\isSpecial;
\Validator::make($request->all(), [
'sum' => new isSpecial() ,
])->validate();
another idea :
Specifying Custom Messages In Language Files
In most cases, you will probably specify your custom messages in a language file instead of passing them directly to the Validator. To do so, add your messages to custom array in the resources/lang/xx/validation.php language file.
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
Simple notice:
- I suggest using HTTP Requests instead use validation in your controller and function direct
Looks like as of Laravel 8, using required_if works as expected, and alternatively will not fall back on required as mentioned previously:
'sum.required_if' => 'This cannot be blank',

Custom error message for `requiredIf` validation in laravel

I'm working on a Laravel 5.8 project and trying to show custom validation messages for a validation which uses the requiredIf validation rule.
Here is how I have it set up:
$validation = Validator::make(
$request->all(),
[
...
'sum' => [
Rule::requiredIf(function() use ($request){
$model = Model::find($request->id);
return $model->is_special; //returns a boolean value
}),
'numeric'
],
...
],
[
...
'sum.required_if' => 'This cannot be blank',
'sum.numeric' => 'Must use a number here',
...
]
);
Now the validation is working correctly and the custom message for the numeric validation shows as should, but the message I get for the requiredIf() method is Laravel's default error message.
I also tried using 'sum.requiredIf' => '...' but that didn't work either and can't seem to find any documentation or example for this scenario.
I was tinkering with this for a while and noticed that for this to work I needed to define
'sum.required' => 'This cannot be blank'
and not 'sum.required_if' => 'This cannot be blank',.
Not sure if this is expected behavior or just a workaround but my deduction is that with the callback Rule::requiredIf(function() use ($request){...}) the parameters :other and :value are not passed so it falls back onto required messaging and I guess this makes sense since required_if and required would not be used on the same :attribute.
Hope this helps anyone who comes across this problem.
First, create a rule name isSpecial or whatever
php artisan make:rule isSpecial
Go to App\Rules\isSpecial.php
private $id;
public function __construct($id) // pass id or what you need
{
//
$this->id=$id;
}
public function passes($attribute, $value) // customize your rules here
{
//
return Model::find($request->id)->is_special;
}
public function message() // here is answer for your question
{
return 'The validation error message.'; // your message
}
in your controller
use App\Rules\isSpecial;
\Validator::make($request->all(), [
'sum' => new isSpecial() ,
])->validate();
another idea :
Specifying Custom Messages In Language Files
In most cases, you will probably specify your custom messages in a language file instead of passing them directly to the Validator. To do so, add your messages to custom array in the resources/lang/xx/validation.php language file.
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
Simple notice:
- I suggest using HTTP Requests instead use validation in your controller and function direct
Looks like as of Laravel 8, using required_if works as expected, and alternatively will not fall back on required as mentioned previously:
'sum.required_if' => 'This cannot be blank',

Validate field as unique with scope in cakephp

I am creating a CakePHP application which have an edit form which contain one text box named air_id. In my table I am using project_id and air_id as composite primary key. So while updating air_id I need to validate uniqueness.
My table structure is like:
project_id air_id
1 test#test.com
1 test1#test.com
Currently I am using cakephp3.0 and I am using validateUnique rule with scope,
Following is my code:
$validator
->add('air_id', [
'unique' => [
'rule' => ['validateUnique', ['scope' => 'project_id']],
'provider' => 'table',
]
]);
And my controller is like this
$projectCustomers = $this->ProjectCustomers->newEntity($formData);
Now it is giving validation message every time. What I need is when I change the value test#test.com to test1#test.com it should raise the error and if I change it to some other value it should not raise the error. Is there something wrong in my validation?
CakePHP Unique Field Rules:
We have cakephp unique field rules that might be even better:
In your table(eg. UsersTable.php):
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(
['air_id', 'project_id'],
'Your validation error here.'
));
return $rules;
}
At the top of your table , don't forget to include this class:
use Cake\ORM\RulesChecker;
See Here (CakePHP Unique Fields Rules).

How do the conditions for validation in Laravel

Just sorry for the dumb question , I know what it is in the documentation . But the documentation does not normally understand how to implement it .
Let's say there is a rule :
public function rules()
{
return [
'title' => 'required|max:15',
'author' => 'required|max:15',
];
}
and it is usually used in the form " Edit " , say the user when editing a product , exceeded character limit of 15 , then leave the message " You have exceeded the character limit ."
PS please show a simple example , he 'll take care of that next to nothing.
Looks like you're using FormRequest for validation. In that case you can add another method named messages() to your request class and return the custom messages from there, following is the example:
public function messages()
{
return [
'required' => 'The attribute: field cannot be left blank',
];
The above example will replace the standard error message the attribute: field is required. with our custom message for all occurrences of required rule, where the attribute: denotes the name of the field under validation.
But if you want to further customise it on per field basis. You can use the dot (.) notation like this:
public function messages()
{
return [
'title.required' => 'The Title must be filled',
];
You're looking for this link in the docs.
As the docs say, define an array of messages that map to the rules, and pass them into the validator. Like so
$rules = [ 'title' => 'max:15' ]
$msgs = [ 'max' => 'Exceeded char limit or whatever!' ]
Validator::make($input, $rules, $msgs);

CakePHP 3.1: Validation for translate behaviour fields (i18n)

I'm trying to add an item including multiple translations in one form with the CakePHP translate behaviour.
How can I validate the translation fields? E.g. make specific languages required?
Let's assume you have a simple items table with a separate translations table items_i18n, set up as described in the book. As simple example the items table has only one field title to translate and I want to save the title in five languages. So I make a form like this (in add view template):
echo $this->Form->create($item, ['controller' => 'Items', 'action' => 'add']);
echo $this->Form->input('title', ['label' => __('English')]);
echo $this->Form->input('_translations.es.title', ['label' => __('Spanish')]);
echo $this->Form->input('_translations.fr.title', ['label' => __('French')]);
echo $this->Form->input('_translations.de.title', ['label' => __('German')]);
echo $this->Form->input('_translations.it.title', ['label' => __('Italian')]);
echo $this->Form->button(__('Save'), ['type' => 'submit']);
echo $this->Form->end();
And saving in the controller (add action/function) like this:
$item = $this->Items->newEntity();
if ($this->request->is('post')) {
$translations = [
'es' => ['title' => $this->request->data['_translations']['es']['title']],
'fr' => ['title' => $this->request->data['_translations']['fr']['title']],
'de' => ['title' => $this->request->data['_translations']['de']['title']],
'it' => ['title' => $this->request->data['_translations']['it']['title']],
];
foreach ($translations as $lang => $data) {
$item->translation($lang)->set($data, ['guard' => false]);
}
$item = $this->Items->patchEntity($item, $this->request->data, ['validate' => 'default'] );
if ( $this->Items->save($item) ) { $this->Flash->success(__('Saved.')); }
else { $this->Flash->error(__('Not saved.')); }
}
$this->set('item', $item);
This is working without validation or if I only have validation rules for the "native" title field (well it should, I simplified the code for stackoverflow and renamed some parts for the example, so maybe there are some typos, but you should get the idea...).
Now let's further assume the languages English (default) and Spanish are required, other language fields are optional. How can I achieve that?
In the ItemsTable I tried something like this for validation:
class ItemsTable extends Table {
public function validationDefault(Validator $validator) {
$validator
// Title English (default field)
->requirePresence('title')
->notEmpty('title', __('Required field'))
// Title Spanish (translate behaviour field)
->requirePresence('_translations.es.title')
->notEmpty('_translations.es.title', __('Required field'))
;
return $validator;
}
}
But this allways brings a validation error "This field is required" because patchEntity($item, $this->request->data); results in the translations being thrown away. I know this by an open issue on GitHub about the saving workflow (btw +1 for this request :).
So currently I'm not sure if there is a way to define validation rules for translation fields when using the CakePHP translation behaviour... Required language fields is only an example, the same problem occurs if you want to validate e.g. the min/max lenght of a input field for a foreign language...
Ok, I think I found a solution. At least temporarily, because I also discovered an issue with NestedValidator and FormHelper.
Currently the validation is still applied to all additional languages. So this is not exactly what I wanted and not the final answer. If you have an idea how I can apply the validation to single languages please leave a comment or answer.
So this is my current intermediate solution with CakePHP 3.1.1:
In the table class add a nested validator for the i18n translation fields.
These nested validation rules will apply to all additional language fields, because they are grouped together in $this->request->data['_translations']:
class ItemsTable extends Table {
public function validationDefault(Validator $validator) {
$validator
// Title English (default language)
->requirePresence('title')
->notEmpty('title')
->add('title', [
'minLength'=>['rule'=>['minLength', 2], 'message' => __('MinLength 2')],
'maxLength'=>['rule'=>['maxLength', 255], 'message' => __('MaxLength 255')],
])
;
// Nested Validation for i18n fields (Translate Behaviour)
// These rules will apply to all 'title' fields in all additional languages
$translationValidator = new Validator();
$translationValidator
->requirePresence('title', 'false') // I want translation to be optional
->allowEmpty('title') // I want translation to be optional
->add('title', [
'minLength'=>['rule'=>['minLength', 5], 'message' => __('MinLength 5')],
'maxLength'=>['rule'=>['maxLength', 255], 'message' => __('MaxLength 255')],
])
;
// Now apply the nested validator to the "main" validation
// ('_translations' is containing the translated input data)
$validator
->addNestedMany('_translations', $translationValidator)
// To prevent "field is required" for the "_translations" data
->requirePresence('_translations', 'false')
->allowEmpty('_translations')
;
return $validator;
}
}
In my test setup I want the translation fields to be optional and have other minLength as the default language. As you can see in the code above, I added allowEmpty and set requirePresence to false for the translation fields. Currently the TranslateBehaviour is still forcing the translation title fields to be required. So I added additionally 'required' => false to the translation input fields in add/edit form:
echo $this->Form->input('_translations.es.title', ['required' => false]);
The separate validation rules are now applied to the translation fields, as shown in the debug result (added temporarily in the controller while testing):
$item = $this->Items->patchEntity($item, $this->request->data);
debug($item);
When you enter only one character in the input fields, the minLength error messages are available in the debug error array.
But currently the FormHelper does not support nested error messages. I reported this issue on GitHub. A temporarily solution to show an error in the form is by checking the error array manually. To do so, add in the Controller:
$item = $this->Items->patchEntity($item, $this->request->data);
if ( !$item->errors() ) {
foreach ($this->request->data['_translations'] as $lang => $data) {
$item->translation($lang)->set($data, ['guard' => false]);
}
}
// Temp workaround for issue#7532:
else {
$this->set('formerrors', $language->errors());
}
And in the add/edit view you can check and use the additional $formerrors array:
if ( isset($formerrors['_translations']['es']['title']) ) { ... }
Another interesting approach is shown in the answer to this question.

Resources