- Validation
- Validation
- Introduction
- Validation Quickstart
- Form Request Validation
- Manually Creating Validators
- Working With Validated Input
- Working With Error Messages
Validation
Validation
Introduction
Laravel provides several different approaches to validate your application’s incoming data. It is most common to use the validate method available on all incoming HTTP requests. However, we will discuss other approaches to validation as well.
Laravel includes a wide variety of convenient validation rules that you may apply to data, even providing the ability to validate if values are unique in a given database table. We’ll cover each of these validation rules in detail so that you are familiar with all of Laravel’s validation features.
Validation Quickstart
To learn about Laravel’s powerful validation features, let’s look at a complete example of validating a form and displaying the error messages back to the user. By reading this high-level overview, you’ll be able to gain a good general understanding of how to validate incoming request data using Laravel:
Defining the Routes
First, let’s assume we have the following routes defined in our routes/web.php file:
use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);
use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);
The GET route will display a form for the user to create a new blog post, while the POST route will store the new blog post in the database.
Creating the Controller
Next, let’s take a look at a simple controller that handles incoming requests to these routes. We’ll leave the store method empty for now:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
/**
* Show the form to create a new blog post.
*/
public function create(): View
{
return view('post.create');
}
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
// Validate and store the blog post...
$post = /** ... */
return to_route('post.show', ['post' => $post->id]);
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
/**
* Show the form to create a new blog post.
*/
public function create(): View
{
return view('post.create');
}
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
// Validate and store the blog post...
$post = /** ... */
return to_route('post.show', ['post' => $post->id]);
}
}
Writing the Validation Logic
Now we are ready to fill in our store method with the logic to validate the new blog post. To do this, we will use the validate method provided by the Illuminate\Http\Request object. If the validation rules pass, your code will keep executing normally; however, if validation fails, an Illuminate\Validation\ValidationException exception will be thrown and the proper error response will automatically be sent back to the user.
If validation fails during a traditional HTTP request, a redirect response to the previous URL will be generated. If the incoming request is an XHR request, a JSON response containing the validation error messages will be returned.
To get a better understanding of the validate method, let’s jump back into the store method:
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
return redirect('/posts');
}
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
return redirect('/posts');
}
As you can see, the validation rules are passed into the validate method. Don’t worry - all available validation rules are documented. Again, if the validation fails, the proper response will automatically be generated. If the validation passes, our controller will continue executing normally.
Alternatively, validation rules may be specified as arrays of rules instead of a single | delimited string:
$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
In addition, you may use the validateWithBag method to validate a request and store any error messages within a named error bag:
$validatedData = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
$validatedData = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
Stopping on First Validation Failure
Sometimes you may wish to stop running validation rules on an attribute after the first validation failure. To do so, assign the bail rule to the attribute:
$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
In this example, if the unique rule on the title attribute fails, the max rule will not be checked. Rules will be validated in the order they are assigned.
A Note on Nested Attributes
If the incoming HTTP request contains “nested” field data, you may specify these fields in your validation rules using “dot” syntax:
$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
On the other hand, if your field name contains a literal period, you can explicitly prevent this from being interpreted as “dot” syntax by escaping the period with a backslash:
$request->validate([
'title' => 'required|unique:posts|max:255',
'v1\.0' => 'required',
]);
$request->validate([
'title' => 'required|unique:posts|max:255',
'v1\.0' => 'required',
]);
Displaying the Validation Errors
So, what if the incoming request fields do not pass the given validation rules? As mentioned previously, Laravel will automatically redirect the user back to their previous location. In addition, all of the validation errors and request input will automatically be flashed to the session.
An $errors variable is shared with all of your application’s views by the Illuminate\View\Middleware\ShareErrorsFromSession middleware, which is provided by the web middleware group. When this middleware is applied an $errors variable will always be available in your views, allowing you to conveniently assume the $errors variable is always defined and can be safely used. The $errors variable will be an instance of Illuminate\Support\MessageBag. For more information on working with this object, check out its documentation.
So, in our example, the user will be redirected to our controller’s create method when validation fails, allowing us to display the error messages in the view:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
Customizing the Error Messages
Laravel’s built-in validation rules each have an error message that is located in your application’s lang/en/validation.php file. If your application does not have a lang directory, you may instruct Laravel to create it using the lang:publish Artisan command.
Within the lang/en/validation.php file, you will find a translation entry for each validation rule. You are free to change or modify these messages based on the needs of your application.
In addition, you may copy this file to another language directory to translate the messages for your application’s language. To learn more about Laravel localization, check out the complete localization documentation.
By default, the Laravel application skeleton does not include the lang directory. If you would like to customize Laravel’s language files, you may publish them via the lang:publish Artisan command.
XHR Requests and Validation
In this example, we used a traditional form to send data to the application. However, many applications receive XHR requests from a JavaScript powered frontend. When using the validate method during an XHR request, Laravel will not generate a redirect response. Instead, Laravel generates a JSON response containing all of the validation errors. This JSON response will be sent with a 422 HTTP status code.
The @error Directive
You may use the @error Blade directive to quickly determine if validation error messages exist for a given attribute. Within an @error directive, you may echo the $message variable to display the error message:
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input
id="title"
type="text"
name="title"
class="@error('title') is-invalid @enderror"
/>
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input
id="title"
type="text"
name="title"
class="@error('title') is-invalid @enderror"
/>
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
If you are using named error bags, you may pass the name of the error bag as the second argument to the @error directive:
<input ... class="@error('title', 'post') is-invalid @enderror">
<input ... class="@error('title', 'post') is-invalid @enderror">
Repopulating Forms
When Laravel generates a redirect response due to a validation error, the framework will automatically flash all of the request’s input to the session. This is done so that you may conveniently access the input during the next request and repopulate the form that the user attempted to submit.
To retrieve flashed input from the previous request, invoke the old method on an instance of Illuminate\Http\Request. The old method will pull the previously flashed input data from the session:
$title = $request->old('title');
$title = $request->old('title');
Laravel also provides a global old helper. If you are displaying old input within a Blade template, it is more convenient to use the old helper to repopulate the form. If no old input exists for the given field, null will be returned:
<input type="text" name="title" value="{{ old('title') }}">
<input type="text" name="title" value="{{ old('title') }}">
A Note on Optional Fields
By default, Laravel includes the TrimStrings and ConvertEmptyStringsToNull middleware in your application’s global middleware stack. Because of this, you will often need to mark your “optional” request fields as nullable if you do not want the validator to consider null values as invalid. For example:
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
In this example, we are specifying that the publish_at field may be either null or a valid date representation. If the nullable modifier is not added to the rule definition, the validator would consider null an invalid date.
Validation Error Response Format
When your application throws a Illuminate\Validation\ValidationException exception and the incoming HTTP request is expecting a JSON response, Laravel will automatically format the error messages for you and return a 422 Unprocessable Entity HTTP response.
Below, you can review an example of the JSON response format for validation errors. Note that nested error keys are flattened into “dot” notation format:
{
"message": "The team name must be a string. (and 4 more errors)",
"errors": {
"team_name": [
"The team name must be a string.",
"The team name must be at least 1 characters."
],
"authorization.role": [
"The selected authorization.role is invalid."
],
"users.0.email": [
"The users.0.email field is required."
],
"users.2.email": [
"The users.2.email must be a valid email address."
]
}
}
{
"message": "The team name must be a string. (and 4 more errors)",
"errors": {
"team_name": [
"The team name must be a string.",
"The team name must be at least 1 characters."
],
"authorization.role": [
"The selected authorization.role is invalid."
],
"users.0.email": [
"The users.0.email field is required."
],
"users.2.email": [
"The users.2.email must be a valid email address."
]
}
}
Form Request Validation
Creating Form Requests
For more complex validation scenarios, you may wish to create a “form request”. Form requests are custom request classes that encapsulate their own validation and authorization logic. To create a form request class, you may use the make:request Artisan CLI command:
php artisan make:request StorePostRequest
php artisan make:request StorePostRequest
The generated form request class will be placed in the app/Http/Requests directory. If this directory does not exist, it will be created when you run the make:request command. Each form request generated by Laravel has two methods: authorize and rules.
As you might have guessed, the authorize method is responsible for determining if the currently authenticated user can perform the action represented by the request, while the rules method returns the validation rules that should apply to the request’s data:
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
You may type-hint any dependencies you require within the rules method’s signature. They will automatically be resolved via the Laravel service container.
So, how are the validation rules evaluated? All you need to do is type-hint the request on your controller method. The incoming form request is validated before the controller method is called, meaning you do not need to clutter your controller with any validation logic:
/**
* Store a new blog post.
*/
public function store(StorePostRequest $request): RedirectResponse
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
// Retrieve a portion of the validated input data...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
/**
* Store a new blog post.
*/
public function store(StorePostRequest $request): RedirectResponse
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
// Retrieve a portion of the validated input data...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an XHR request, an HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.
Need to add real-time form request validation to your Inertia powered Laravel frontend? Check out Laravel Precognition.
Performing Additional Validation
Sometimes you need to perform additional validation after your initial validation is complete. You can accomplish this using the form request’s after method.
The after method should return an array of callables or closures which will be invoked after validation is complete. The given callables will receive an Illuminate\Validation\Validator instance, allowing you to raise additional error messages if necessary:
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'Something is wrong with this field!'
);
}
}
];
}
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'Something is wrong with this field!'
);
}
}
];
}
As noted, the array returned by the after method may also contain invokable classes. The __invoke method of these classes will receive an Illuminate\Validation\Validator instance:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}
Stopping on the First Validation Failure
By adding a stopOnFirstFailure property to your request class, you may inform the validator that it should stop validating all attributes once a single validation failure has occurred:
/**
* Indicates if the validator should stop on the first rule failure.
*
* @var bool
*/
protected $stopOnFirstFailure = true;
/**
* Indicates if the validator should stop on the first rule failure.
*
* @var bool
*/
protected $stopOnFirstFailure = true;
Customizing the Redirect Location
When form request validation fails, a redirect response will be generated to send the user back to their previous location. However, you are free to customize this behavior. To do so, define a $redirect property on your form request:
/**
* The URI that users should be redirected to if validation fails.
*
* @var string
*/
protected $redirect = '/dashboard';
/**
* The URI that users should be redirected to if validation fails.
*
* @var string
*/
protected $redirect = '/dashboard';
Or, if you would like to redirect users to a named route, you may define a $redirectRoute property instead:
/**
* The route that users should be redirected to if validation fails.
*
* @var string
*/
protected $redirectRoute = 'dashboard';
/**
* The route that users should be redirected to if validation fails.
*
* @var string
*/
protected $redirectRoute = 'dashboard';
Authorizing Form Requests
The form request class also contains an authorize method. Within this method, you may determine if the authenticated user actually has the authority to update a given resource. For example, you may determine if a user actually owns a blog comment they are attempting to update. Most likely, you will interact with your authorization gates and policies within this method:
use App\Models\Comment;
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
use App\Models\Comment;
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
Since all form requests extend the base Laravel request class, we may use the user method to access the currently authenticated user. Also, note the call to the route method in the example above. This method grants you access to the URI parameters defined on the route being called, such as the {comment} parameter in the example below:
Route::post('/comment/{comment}');
Route::post('/comment/{comment}');
Therefore, if your application is taking advantage of route model binding, your code may be made even more succinct by accessing the resolved model as a property of the request:
return $this->user()->can('update', $this->comment);
return $this->user()->can('update', $this->comment);
If the authorize method returns false, an HTTP response with a 403 status code will automatically be returned and your controller method will not execute.
If you plan to handle authorization logic for the request in another part of your application, you may remove the authorize method completely, or simply return true:
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
You may type-hint any dependencies you need within the authorize method’s signature. They will automatically be resolved via the Laravel service container.
Customizing the Error Messages
You may customize the error messages used by the form request by overriding the messages method. This method should return an array of attribute / rule pairs and their corresponding error messages:
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
Customizing the Validation Attributes
Many of Laravel’s built-in validation rule error messages contain an :attribute placeholder. If you would like the :attribute placeholder of your validation message to be replaced with a custom attribute name, you may specify the custom names by overriding the attributes method. This method should return an array of attribute / name pairs:
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => 'email address',
];
}
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => 'email address',
];
}
Preparing Input for Validation
If you need to prepare or sanitize any data from the request before you apply your validation rules, you may use the prepareForValidation method:
use Illuminate\Support\Str;
/**
* Prepare the data for validation.
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}
use Illuminate\Support\Str;
/**
* Prepare the data for validation.
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}
Likewise, if you need to normalize any request data after validation is complete, you may use the passedValidation method:
/**
* Handle a passed validation attempt.
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}
/**
* Handle a passed validation attempt.
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}
Manually Creating Validators
If you do not want to use the validate method on the request, you may create a validator instance manually using the Validator facade. The make method on the facade generates a new validator instance:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('/post/create')
->withErrors($validator)
->withInput();
}
// Retrieve the validated input...
$validated = $validator->validated();
// Retrieve a portion of the validated input...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('/post/create')
->withErrors($validator)
->withInput();
}
// Retrieve the validated input...
$validated = $validator->validated();
// Retrieve a portion of the validated input...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
}
The first argument passed to the make method is the data under validation. The second argument is an array of the validation rules that should be applied to the data.
After determining whether the request validation failed, you may use the withErrors method to flash the error messages to the session. When using this method, the $errors variable will automatically be shared with your views after redirection, allowing you to easily display them back to the user. The withErrors method accepts a validator, a MessageBag, or a PHP array.
Stopping on First Validation Failure
The stopOnFirstFailure method will inform the validator that it should stop validating all attributes once a single validation failure has occurred:
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}
Automatic Redirection
If you would like to create a validator instance manually but still take advantage of the automatic redirection offered by the HTTP request’s validate method, you may call the validate method on an existing validator instance. If validation fails, the user will automatically be redirected or, in the case of an XHR request, a JSON response will be returned:
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
You may use the validateWithBag method to store the error messages in a named error bag if validation fails:
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validateWithBag('post');
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validateWithBag('post');
Named Error Bags
If you have multiple forms on a single page, you may wish to name the MessageBag containing the validation errors, allowing you to retrieve the error messages for a specific form. To achieve this, pass a name as the second argument to withErrors:
return redirect('/register')->withErrors($validator, 'login');
return redirect('/register')->withErrors($validator, 'login');
You may then access the named MessageBag instance from the $errors variable:
{{ $errors->login->first('email') }}
{{ $errors->login->first('email') }}
Customizing the Error Messages
If needed, you may provide custom error messages that a validator instance should use instead of the default error messages provided by Laravel. There are several ways to specify custom messages. First, you may pass the custom messages as the third argument to the Validator::make method:
$validator = Validator::make($input, $rules, $messages = [
'required' => 'The :attribute field is required.',
]);
$validator = Validator::make($input, $rules, $messages = [
'required' => 'The :attribute field is required.',
]);
In this example, the :attribute placeholder will be replaced by the actual name of the field under validation. You may also utilize other placeholders in validation messages. For example:
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute value :input is not between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute value :input is not between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
Specifying a Custom Message for a Given Attribute
Sometimes you may wish to specify a custom error message only for a specific attribute. You may do so using “dot” notation. Specify the attribute’s name first, followed by the rule:
$messages = [
'email.required' => 'We need to know your email address!',
];
$messages = [
'email.required' => 'We need to know your email address!',
];
Specifying Custom Attribute Values
Many of Laravel’s built-in error messages include an :attribute placeholder that is replaced with the name of the field or attribute under validation. To customize the values used to replace these placeholders for specific fields, you may pass an array of custom attributes as the fourth argument to the Validator::make method:
$validator = Validator::make($input, $rules, $messages, [
'email' => 'email address',
]);
$validator = Validator::make($input, $rules, $messages, [
'email' => 'email address',
]);
Performing Additional Validation
Sometimes you need to perform additional validation after your initial validation is complete. You can accomplish this using the validator’s after method. The after method accepts a closure or an array of callables which will be invoked after validation is complete. The given callables will receive an Illuminate\Validation\Validator instance, allowing you to raise additional error messages if necessary:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(/* ... */);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field', 'Something is wrong with this field!'
);
}
});
if ($validator->fails()) {
// ...
}
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(/* ... */);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field', 'Something is wrong with this field!'
);
}
});
if ($validator->fails()) {
// ...
}
As noted, the after method also accepts an array of callables, which is particularly convenient if your “after validation” logic is encapsulated in invokable classes, which will receive an Illuminate\Validation\Validator instance via their __invoke method:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
$validator->after([
new ValidateUserStatus,
new ValidateShippingTime,
function ($validator) {
// ...
},
]);
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
$validator->after([
new ValidateUserStatus,
new ValidateShippingTime,
function ($validator) {
// ...
},
]);
Working With Validated Input
After validating incoming request data using a form request or a manually created validator instance, you may wish to retrieve the incoming request data that actually underwent validation. This can be accomplished in several ways. First, you may call the validated method on a form request or validator instance. This method returns an array of the data that was validated:
$validated = $request->validated();
$validated = $validator->validated();
$validated = $request->validated();
$validated = $validator->validated();
Alternatively, you may call the safe method on a form request or validator instance. This method returns an instance of Illuminate\Support\ValidatedInput. This object exposes only, except, and all methods to retrieve a subset of the validated data or the entire array of validated data:
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();
In addition, the Illuminate\Support\ValidatedInput instance may be iterated over and accessed like an array:
// Validated data may be iterated...
foreach ($request->safe() as $key => $value) {
// ...
}
// Validated data may be accessed as an array...
$validated = $request->safe();
$email = $validated['email'];
// Validated data may be iterated...
foreach ($request->safe() as $key => $value) {
// ...
}
// Validated data may be accessed as an array...
$validated = $request->safe();
$email = $validated['email'];
If you would like to add additional fields to the validated data, you may call the merge method:
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);
If you would like to retrieve the validated data as a collection instance, you may call the collect method:
$collection = $request->safe()->collect();
$collection = $request->safe()->collect();
Working With Error Messages
After calling the errors method on a Validator instance, you will receive an Illuminate\Support\MessageBag instance, which has a variety of convenient methods for working with error messages. The $errors variable that is automatically made available to all views is also an instance of the MessageBag class.
Retrieving the First Error Message for a Field
To retrieve the first error message for a given field, use the first method:
$errors = $validator->errors();
echo $errors->first('email');
$errors = $validator->errors();
echo $errors->first('email');
Retrieving All Error Messages for a Field
If you need to retrieve an array of all the messages for a given field, use the get method:
foreach ($errors->get('email') as $message) {
// ...
}
foreach ($errors->get('email') as $message) {
// ...
}
If you are validating an array form field, you may retrieve all of the messages for each of the array elements using the * character:
foreach ($errors->get('attachments.*') as $message) {
// ...
}
foreach ($errors->get('attachments.*') as $message) {
// ...
}
Retrieving All Error Messages for All Fields
To retrieve an array of all messages for all fields, use the all method:
foreach ($errors->all() as $message) {
// ...
}
foreach ($errors->all() as $message) {
// ...
}
Determining if Messages Exist for a Field
The has method may be used to determine if any error messages exist for a given field:
if ($errors->has('email')) {
// ...
}
if ($errors->has('email')) {
// ...
}
Specifying Custom Messages in Language Files
Laravel’s built-in validation rules each have an error message that is located in your application’s lang/en/validation.php file. If your application does not have a lang directory, you may instruct Laravel to create it using the lang:publish Artisan command.
Within the lang/en/validation.php file, you will find a translation entry for each validation rule. You are free to change or modify these messages based on the needs of your application.
In addition, you may copy this file to another language directory to translate the messages for your application’s language. To learn more about Laravel localization, check out the complete localization documentation.
By default, the Laravel application skeleton does not include the lang directory. If you would like to customize Laravel’s language files, you may publish them via the lang:publish Artisan command.
Custom Messages for Specific Attributes
You may customize the error messages used for specified attribute and rule combinations within your application’s validation language files. To do so, add your message customizations to the custom array of your application’s lang/xx/validation.php language file:
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],
Specifying Attributes in Language Files
Many of Laravel’s built-in error messages include an :attribute placeholder that is replaced with the name of the field or attribute under validation. If you would like the :attribute portion of your validation message to be replaced with a custom value, you may specify the custom attribute name in the attributes array of your lang/xx/validation.php language file:
'attributes' => [
'email' => 'email address',
],
'attributes' => [
'email' => 'email address',
],
By default, the Laravel application skeleton does not include the lang directory. If you would like to customize Laravel’s language files, you may publish them via the lang:publish Artisan command.
Specifying Values in Language Files
Some of Laravel’s built-in validation rule error messages contain a :value placeholder that is replaced with the current value of the request attribute. However, you may occasionally need the :value portion of your validation message to be replaced with a custom representation of the value. For example, consider the following rule that specifies that a credit card number is required if the payment_type has a value of cc:
Validator::make($request->all(), [
'credit_card_number' => 'required_if:payment_type,cc'
]);
Validator::make($request->all(), [
'credit_card_number' => 'required_if:payment_type,cc'
]);
If this validation rule fails, it will produce the following error message:
The credit card number field is required when payment type is cc.
The credit card number field is required when payment type is cc.
Instead of displaying cc as the payment type value, you may specify a more user-friendly value representation in your lang/xx/validation.php language file by defining a values array:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
By default, the Laravel application skeleton does not include the lang directory. If you would like to customize Laravel’s language files, you may publish them via the lang:publish Artisan command.
After defining this value, the validation rule will produce the following error message:
The credit card number field is required when payment type is credit card.
The credit card number field is required when payment type is credit card.
(本文超出站点单文档体积上限,已按小节截断)
