Get error message from Laravel validation - php

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.

Related

How to solve Argument 1 passed to CodeIgniter\Validation\Validation::run() must be of the type array or null, object given?

I'm facing a problem while working on file validation in Codeigniter 4. Codes are given below.
Codes in the validation file are:
public $image = [
'image_path' => [
'label' => 'Image',
'rules' => 'uploaded[image_path]|is_image[image_path]|max_size[image_path, 1024]|mime_in[image_path,image/jpg,image/jpeg,image/png]'
]
];
And, codes in the controller are:
if($image->isValid() && !$image->hasMoved()):
if(!$this->validation->run($image, "image")):
$this->session->setFlashdata('image_errors', $this->validation->getErrors() ?? "");
return redirect()->back()->withInput();
endif;
endif;
But whenever I'm trying to run these code, the following error happened:
Argument 1 passed to CodeIgniter\Validation\Validation::run() must be of the type array or null, object given.
Please suggest me possible solution for this.
Thank you.
When we need to validate form in the controller we follow this steps:
use validate() method instead of using $validation property
see Controller Validate Data
set flashdata within recirect()->with() method
see Common functions
if condition syntax should be with brackets { }, use if else endif in view files only (optional).
see Alternate Syntax
It's very important and recommended to read User Guide
if ($image->isValid() && ! $image->hasMoved())
{
if (! $this->validate('image'))
{
return redirect()->back()->withInput()->with('image_errors', $this->validator->getErrors())
}
}
if you want to use validation class just do this
if ($image->isValid() && ! $image->hasMoved())
{
$this->validation->setRuleGroup('image');
if (! $this->validation->withRequest($this->request)->run())
{
return redirect()->back()->withInput()->with('image_errors', $this->validation->getErrors())
}
}
I hope it will work fine with your code.

How do you display your own error messages with laravel-jsvalidation?

I would like to figure out how to create your own error messages for your rules (e.g. regular expression rules) to be reused by both server PHP and client javascript (using jqueryvalidation through laravel-jsvalidation )
I have tried and can not make it work, and below is a small example to show what I am trying to do but it does not work.
What am I doing wrong?
My small example:
In the file "routes\web.php":
Route::get('/minimal_example_laravel_jsvalidation', function() {
// Of course these rules should not really be defined here since
// the purpose of the rules is to also reuse them from PHP Laravel code
// but my problem is now how to generate javascript that can
// reuse the same rules and therefore I just put the rules and messages
// here in this minimalistic example illustrating the problem
$rules = [
'three_digits' => 'required|regex:/^\d{3}$/'
];
$messages = [
'three_digits' => 'Must be exactly three digits'
];
$validator = JsValidator::make($rules, $messages);
return view('minimal_example_laravel_jsvalidation')->with("validator", $validator);
});
In the file "resources\views\minimal_example_laravel_jsvalidation.blade.php":
...
{!! $validator->selector('#myForm') !!}
...
When using the URL
http://localhost:8000/minimal_example_laravel_jsvalidation
with the web browser and then "view source" I can see that the following javascript code has been generated by the above "$validator->selector" :
jQuery(document).ready(function(){
$("#myForm").each(function() {
$(this).validate({
errorElement: 'span',
errorClass: 'invalid-feedback',
errorPlacement: function (error, element) {
if (element.parent('.input-group').length ||
element.prop('type') === 'checkbox' || element.prop('type') === 'radio') {
error.insertAfter(element.parent());
// else just place the validation message immediately after the input
} else {
error.insertAfter(element);
}
},
highlight: function (element) {
$(element).closest('.form-control').removeClass('is-valid').addClass('is-invalid'); // add the Bootstrap error class to the control group
},
unhighlight: function(element) {
$(element).closest('.form-control').removeClass('is-invalid').addClass('is-valid');
},
success: function (element) {
$(element).closest('.form-control').removeClass('is-invalid').addClass('is-valid'); // remove the Boostrap error class from the control group
},
focusInvalid: true,
rules: {"three_digits":{"laravelValidation":[["Required",[],"The three digits field is required.",true],["Regex",["\/^\\d{3}$\/"],"The three digits format is invalid.",false]]}} });
});
});
Indeed, the error message I get when not writing three digits in the field through my web browser, is as above "The three digits format is invalid." while I expect that it instead should be "Must be exactly three digits" as I defined in the "$messages" array.
I have seen that it is possible with Laravel to create PHP classes with "Custom Validation Rules" where you also can define custom messages, but as far as I understand, if you use those custom rules with laravel-jsvalidation then the validation must be done with AJAX instead of javascript validation directly within the browser, which is what I want to do instead of doing AJAX calls.
I am using these versions:
laravel/framework v7.4.0
proengsoft/laravel-jsvalidation 3.0.0
Try changing messages array like this,
$messages = [
'three_digits.required' => 'Three Digits field is required',
'three_digits.regex' => 'Must be exactly three digits'
];
Note I have added rule also to the message key. ('three_digits.required')

Add multiple custom messages in Laravel validation

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

Validator - return all error messages

Currently the Validator in Laravel only appears to return one error message per field, despite the field potentially having multiple rules and messages. (Note: I'm currently passing an empty array as $data to Validator::make)
What I'm trying to do is build an array of each field's rules and messages that could potentially be re-used for front end validation. Something like this:
{
"name": {
"required": [
"The name field is required."
],
"max:255": [
"The name field may not be greater than 255."
]
},
"email": {
"required": [
"The email field is required."
],
"email": [
"The email field must be a valid email address."
],
"max:255": [
"The email field may not be greater than 255."
]
}
}
The getMessage method in Illuminate\Validation\Validator looks like it would get me close to being able to construct something myself, however it is a protected method.
Does anyone know of a way to get a Validator instance to output all rules and messages?
Currently the Validator in Laravel only appears to return one error message per field, despite the field potentially having multiple rules and messages.
Validation of given field stops as soon as a single validation rule fails. That's the reason you're getting only single error message per field.
As of fetching the validation messages like in the example you provided, Laravel's validator does not provide such option, but you could easily achieve that by extending the Validator class.
First, create your new class:
<?php namespace Your\Namespace;
use Illuminate\Validation\Validator as BaseValidator;
class Validator extends BaseValidator {
public function getValidationMessages() {
$messages = [];
foreach ($this->rules as $attribute => $rules) {
foreach ($rules as $rule) {
$messages[$attribute][$rule] = $this->getMessage($attribute, $rule);
}
}
return $messages;
}
}
As you can see the output is a bit different than your example. There is no need to return an array of messages for given attribute and rule, as there will be always only one message in the array, so I'm just storing a string there.
Second, you need to make sure that your validator class is used. In order to achieve that, you'll need to register your own validator resolver with Validator facade:
Validator::resolver(function($translator, array $data, array $rules, array $messages, array $customAttributes) {
return new \Your\Namespace\Validator($translator, $data, $rules, $messages, $customAttributes);
});
You can do this in your AppServiceProvider::boot() method.
Now, in order to get validation messages for given validator, you just need to call:
Validator::make($data, $rules)->getValidationMessages();
Keep in mind this code hasn't been tested. Let me know if you see any issues or typos with the code and I'll be more than happy to get that working for you.

Laravel 4 - how to return all validation error messages for all fields as a JSON structure?

I'm upgrading from Laravel 3 to Laravel 4. My app has some AJAX-only forms that are rendered client-side (i.e. there are no server-side views). Therefore, instead of passing validation errors to views with the withErrors() method, I've been returning the validation error objects to the client as JSON structures.
In Laravel 3, I had this:
$validation = Validator::make(Input::all(), $rules);
if($validation->fails())
{
return json_encode($validation->errors);
}
//else handle task
But in Laravel 4, the error messages are protected:
$validation = Validator::make(Input::all(), $rules);
if($validation->fails())
{
var_dump($validation->messages());
return json_encode($validation->messages());
}
//else handle task
var_dump($validation->messages()) returns:
object(Illuminate\Support\MessageBag)[333]
protected 'messages' =>
array (size=1)
'delete_confirm_password' =>
array (size=1)
0 => string 'The delete confirm password field is required.' (length=46)
protected 'format' => string ':message' (length=8)
json_encode($validation->messages) returns
{}
Question: how do I return all the validation error messages for all fields as a JSON structure in Laravel 4?
Simply use toJson() method.
return $validator->messages()->toJson();
Here is another way that let u add HTTP code to the response:
return Response::json($validation->messages(), 500);
I discovered it was possible to use the toArray() method:
return json_encode($validation->messages()->toArray());
I think that this is the Laravel way to get the error messages. There are special methods to get them. So here how I do this stuff:
return Response::json($validator->errors()->getMessages(), 400);
This produces output in the following format:
{
"field_name": [
"Error message"
]
}

Categories