Add multiple custom messages in Laravel validation - php

I need to add multiple custom error messages like this and both needs to be displayed as validations messages. I have the following code :
if (!$condition1) {
$error[] = "Condition 1 needs to be satisfied";
$validation = false;
}
if (!$condition2) {
$error[] = "Condition 2 needs to be satisfied";
$validation = false;
}
$validator->setCustomMessages($error);
But here I am getting only one message that is the first one even if it is entering to second condition. I have tried to add $validator->setCustomMessages("Message"); in each of the conditions, but it is also doing the same thing.

Why are you using conditionals for validation?
This is what I use to handle validation for uploading photos in my controller.
You have a custom error message for 'required' and one for 'size' (which refers to the size of the photos array).
To add another custom message, just pipe on another rule and its corresponding error message using dot notation.
Only after all rules are satisfied then the code continues execution.
$this->validate($request,
[
'photos' => 'required|size:4'
],
[
'photos.required' => 'Photos are Required',
'photos.size' => 'You must upload 4 Photos'
]
);

Try to change $validator->setCustomMessages($error); for $validator->getMessageBag()->merge($error);
Now if you do $validator->errors()->getMessages() you must have your array with both errors

Related

Laravel 5.4 "Complex Conditional Validation"

I was trying to make a complex validation with a Request file
"algunTexto" => "required" ,
"archivo_texto" => "required_if:algunTexto,si|file|mimes:doc,docx,pages,txt|max:10000" ,
It wasn't working, because the request was returning errors that the file must be "doc, docx, etc." and the input must be a file, so I decided to try adding bail
"archivo_texto" => "bail|required_if:algunTexto,si|file|mimes:doc,docx,pages,txt|max:10000" ,
Now the "doc, docx" error was no longer appearing but the other one that the input must be a file was still there.
I made a research and ended up using this:
$data = $request->all();
$validator = validator($data,
[
'archivo_texto' => 'required_if:algunTexto,si'
]
);
$res = $validator->sometimes('archivo_texto', 'file|mimes:doc,docx,pages,txt|max:10000', function($data){
return $data->algunTexto == 'si';
});
But now, even if the radio button named "algunTexto" equals "si", and I don't upload any file on "archivo_texto", I get no error.
What am I doing wrong?
Now it works with the last attemp I made, I missed these lines:
if($validator->fails()){
return back()->withErrors($validator);
}
I thought that it would return automatically with errors just like a Request does, sorry.

CakePHP 3 - Cake trying to validate notEmpty for some reason

My table is throwing a default "notEmpty" validation error, even though I have not written any validation of the sort.
Basic validation in my Table class:
public function validationDefault(Validator $validator)
{
return $validator->requirePresence('my_field', 'create', 'Custom error message');
}
Data being set:
['my_field' => null]
As far as I can tell from the docs, this should not fail validation.
Key presence is checked by using array_key_exists() so that null values will count as present.
However, what is actually happening is that validation is failing with a message:
'my_field' => 'This field cannot be left empty'
This is Cake's default message for the notEmpty() validation function, so where is it coming from? I want it to allow the null value. My database field also allows NULL.
Edit
I have managed to solve the issue by adding allowEmpty() to the validation for that field. This would, therefore, seem to show that Cake assumes that if your field is required you also want it validate notEmpty() by default, even if you didn't tell it so.
This directly contradicts the documentation line I showed above:
Key presence is checked by using array_key_exists() so that null values will count as present.
So does the documentation need to be updated, or is it a bug?
Although it is not mentioned in the Cake 3 documentation, required fields are not allowed to be empty by default, so you have to explicitly state that the field is required and allowed to be empty.
public function validationDefault(Validator $validator)
{
return $validator
->requirePresence('my_field', 'create', 'Custom error message')
->allowEmpty('my_field', 'create');
}
This had me stumped for a while. The default behaviour is not at all intuitive. Here's some code that applies conditional validation on an array of scenarios coded as [ targetField, whenConditionalField, isConditionalValue ]
public function validationRegister()
{
$validator = new Validator();
$conditionals = [ ['shipAddress1','shipEqualsBill','N'], ['shipTown','shipEqualsBill','N'], ['shipPostcode','shipEqualsBill','N'] ];
foreach($conditionals as $c) {
if (!is_array($c[2])) $c[2] = [$c[2]];
// As #BadHorsie says, this is the crucial line
$validator->allowEmpty($c[0]);
$validator->add($c[0], 'notEmpty', [
'rule' => 'notEmpty',
'on' => function ($context) use ($c) {
return (!empty($context['data'][$c[1]]) && in_array($context['data'][$c[1]], $c[2]));
}
]);
}
return $validator;
}
So, in this case, if the user selects that the Shipping Address is not the same as the Billing Address, various shipping fields must then be notEmpty.

Get error message from Laravel validation

I use Laravel built-in validator and I want to get the first error message
if ($validator->fails()) {
$error = $validator->messages()->toJson();
.....
}
This is the result when I print error
{"name":["The name must be at least 5 characters."],"alamat":["The address must be at least 5 characters."]}
In the example above, I want to get the first error, which is "The name must be at least 5 characters.". How can I do that?
Try this:
if ($validator->fails()) {
$error = $validator->errors()->first();
}
As per 2019 Laravel 5.8 and above to get all the error messages from the validator is as easy as this:
// create the validator and make a validation here...
if ($validator->fails()) {
$fieldsWithErrorMessagesArray = $validator->messages()->get('*');
}
You will get the array of arrays of the fields' names and error messages. Something like this:
[
'price'=>
[
0 => 'Price must be integer',
1 => 'Price must be greater than 0'
]
'password' => [
[
0 => 'Password is required'
]
]
]
You can use other validation messages getters that Illuminate\Support\MessageBag class provides (it is actually the object type that $validator->messages() above returns).
Message Bag Error Messages Additional Helpers
Go to your_laravel_project_dir/vendor/illuminate/support/MessageBag.php and find some useful methods like keys, has, hasAny, first, all, isEmpty etc. that you may need while checking for particular validation errors and customizing HTTP response messages.
It is easy to understand what they do by the look at the source code. Here is the Laravel 5.8 API reference though probably less useful than the source code.
In your ajax request, when you get the data, try data.name.
This will give you the error message for the name field.
$.ajax({
url: "/your-save-url",
type: "post",
data: serializedData,
success: function(data) { alert(data.name)}
});
If validation fails, the withErrors method can be used to flash the error messages to the session. This is an array and this method will automatically share $errors with all views after redirection.
return redirect('register')->withErrors($validator, 'login');
The MessageBag can be accessed using the instance from the $errors variable:
{{ $errors->login->first('email') }}
Form API docs
Hope this is helpful.
If you are using toastr style error displaying, this will work:
#if(session()->get('errors'))
toastr.error("{{ session()->get('errors')->first() }}");
#endif
for getting all errors, try this:
if ($validator->fails()) {
$error = $validator->errors()->all();
}
if you want to do it inside the controller you can:
Arr::first(Arr::flatten($validator->messages()->get('*')))
you will get the first text message
The email must be accepted.

cakephp3 custom validation

I have a duration field that sometimes can be empty and sometimes can't, depending on the other data sent by the form. So I'm trying to do custom validation in CakePHP3.
In my table I did
public function validationDefault(Validator $validator)
{
$validator
->add('duration', 'durationOk', [
'rule' => 'isDurationOk',
'message' => 'duration is not OK',
'provider' => 'table'
]);
return $validator;
}
public function isDurationOk($value, $context)
{
// do some logic
return false; // Always return false, just for test
}
Now when I set the value for duration field I get an 'duration is not OK' error (as expected). But when I let the value empty I get a 'This field cannot be left empty' error.
So I added:
->allowEmpty('duration');
But in this case when duration is empty I don't get an error at all.
Am I doing something wrong or it's just me don't understanding how validation works?
Let me read the book for you:
Conditional Validation
When defining validation rules, you can use the on key to define when
a validation rule should be applied. If left undefined, the rule will
always be applied. Other valid values are create and update. Using one
of these values will make the rule apply to only create or update
operations.
Additionally, you can provide a callable function that will determine
whether or not a particular rule should be applied:
'on' => function ($context) {
// Do your "other data" checks here
return !empty($context['data']['other_data']);
}
So just define the conditions depending on your "other data" in the callback to apply the rule only when the conditons are true.
Alternatively you can manipulate the plain form data even before it gets validated in the beforeMarshal() callback of the table and change the form data as needed or load another validator or modify the validator.

Messages not working on Zend_Form_Element_Text

In a form, I have the following element:
$email = new Zend_Form_Element_Text('username');
$email
->setLabel($this->getView()->l('E-mail'))
->setRequired(TRUE)
->addValidator('EmailAddress')
->addValidator('Db_NoRecordExists', true,
array(
'table' => 'pf_user',
'field' => 'email',
'messages' => array(
'recordFound' => 'This username is already registered',
)
))
->setErrorMessages(array(
'emailAddressInvalidFormat' => 'You must enter a valid e-mail',
'isEmpty' => 'You must enter an e-mail',
'recordFound' => 'This e-mail has already registered in out database'
));
$form->addElement($email)
the problem is that I always I get the same message "You must enter a valid e-mail" (the first one). Does anybody knows what is the mistake??
Actually, what you're doing is the following :
You set the errors on the element
Zend now thinks that the element did not validate correctly and that the first error is
"You must enter a valid e-mail"
When you display the form, since you set errors, Zend will find them and display the first one it finds. If you switch the order then you'll find that whichever error you put up top will be the error you get.
The more correct way is to set the custom messages in the validator. When the validators are called to validate the element, if the validation fails, the validator will call the setErrorMessages on the element to set the custom errors you specify. Use this type of code below to set your custom messages.
$element->addValidator( array( 'Db_NoRecordExists', true, array(
'messages' = array(
Zend_Validate_Db_Abstract::ERROR_NO_RECORD_FOUND => 'Myy custom no error record',
Zend_Validate_Db_Abstract::ERROR_RECORD_FOUND => 'My custom record error'
)
) ) );
You'll find that usually there are consts in each validator class that specify one type of error. In this case, the consts are in the parent class of the DB_NoRecordExists class but usually you'll find them directly in the class near the top.
Basically by passing 'true' as second parameter to addValidator() you are saying the validator to break the chain whenever validator fails . Since "" is not an valid email address hence the first email validator fails and breaks the chain
From Zend Doc http://framework.zend.com/manual/en/zend.validate.validator_chains.html
In some cases it makes sense to have a validator break the chain if
its validation process fails. Zend_Validate supports such use cases
with the second parameter to the addValidator() method. By setting
$breakChainOnFailure to TRUE, the added validator will break the chain
execution upon failure, which avoids running any other validations
that are determined to be unnecessary or inappropriate for the
situation. If the above example were written as follows, then the
alphanumeric validation would not occur if the string length
validation fails:
$validatorChain->addValidator(
new Zend_Validate_StringLength(array('min' => 6,
'max' => 12)),
true)
->addValidator(new Zend_Validate_Alnum());

Categories