Debug School

rakesh kumar
rakesh kumar

Posted on

Validation

Introduction
Validation Quickstart
Defining The Routes
Creating The Controller
Writing The Validation Logic
Displaying The Validation Errors
Repopulating Forms
A Note On Optional Fields
Validation Error Response Format
Form Request Validation
Creating Form Requests
Authorizing Form Requests
Customizing The Error Messages
Preparing Input For Validation
Manually Creating Validators
Automatic Redirection
Named Error Bags
Customizing The Error Messages
After Validation Hook
Working With Validated Input
Working With Error Messages
Specifying Custom Messages In Language Files
Specifying Attributes In Language Files
Specifying Values In Language Files
Available Validation Rules
Conditionally Adding Rules
Validating Arrays
Validating Nested Array Input
Error Message Indexes & Positions
Validating Files
Validating Passwords
Custom Validation Rules
Using Rule Objects
Using Closures
Implicit Rules

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.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // The blog post is valid...
}
Enter fullscreen mode Exit fullscreen mode

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'],
]);
Enter fullscreen mode Exit fullscreen mode

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'],
]);
Enter fullscreen mode Exit fullscreen mode

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',
]);
Enter fullscreen mode Exit fullscreen mode

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',
]);
Enter fullscreen mode Exit fullscreen mode

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',
]);
Enter fullscreen mode Exit fullscreen mode

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:

<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
Enter fullscreen mode Exit fullscreen mode

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:


<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
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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') }}">
Enter fullscreen mode Exit fullscreen mode

A Note On Optional Fields
By default, Laravel includes the TrimStrings and ConvertEmptyStringsToNull middleware in your application's global middleware stack. These middleware are listed in the stack by the App\Http\Kernel class. 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',
]);
Enter fullscreen mode Exit fullscreen mode

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."
        ]
    }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 */
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}
Enter fullscreen mode Exit fullscreen mode

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. *
  • @param \App\Http\Requests\StorePostRequest $request
  • @return Illuminate\Http\Response */
public function store(StorePostRequest $request)
{
    // 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']);
}
Enter fullscreen mode Exit fullscreen mode

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.',
]);
Enter fullscreen mode Exit fullscreen mode

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',
];
Enter fullscreen mode Exit fullscreen mode

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!',
];
Enter fullscreen mode Exit fullscreen mode

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',
]);
Enter fullscreen mode Exit fullscreen mode

After Validation Hook
You may also attach callbacks to be run after validation is completed. This allows you to easily perform further validation and even add more error messages to the message collection. To get started, call the after method on a validator instance:

$validator = Validator::make(/* ... */);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add(
            'field', 'Something is wrong with this field!'
        );
    }
});

if ($validator->fails()) {
    //
}
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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) {
    //
}
Enter fullscreen mode Exit fullscreen mode

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) {
    //
}
Enter fullscreen mode Exit fullscreen mode

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) {
    //
}
Enter fullscreen mode Exit fullscreen mode

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')) {
    //
}
Enter fullscreen mode Exit fullscreen mode

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. Within this 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 translation language directory to translate the messages for your application's language. To learn more about Laravel localization, check out the complete localization documentation.

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!'
    ],
],
Enter fullscreen mode Exit fullscreen mode

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',
],
Enter fullscreen mode Exit fullscreen mode

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'
]);
Enter fullscreen mode Exit fullscreen mode

If this validation rule fails, it will produce the following error message:

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'
    ],
],
Enter fullscreen mode Exit fullscreen mode

After defining this value, the validation rule will produce the following error message:

Available Validation Rules
Below is a list of all available validation rules and their function:
Refer
Accepted
Accepted If
Active URL
After (Date)
After Or Equal (Date)
Alpha
Alpha Dash
Alpha Numeric
Array
Bail
Before (Date)
Before Or Equal (Date)
Between
Boolean
Confirmed
Current Password
Date
Date Equals
Date Format
Declined
Declined If
Different
Digits
Digits Between
Dimensions (Image Files)
Distinct
Doesnt Start With
Doesnt End With
Email
Ends With
Enum
Exclude
Exclude If
Exclude Unless
Exclude With
Exclude Without
Exists (Database)
File
Filled
Greater Than
Greater Than Or Equal
Image (File)
In
In Array
Integer
IP Address
JSON
Less Than
Less Than Or Equal
MAC Address
Max
Max Digits
MIME Types
MIME Type By File Extension
Min
Min Digits
Multiple Of
Not In
Not Regex
Nullable
Numeric
Password
Present
Prohibited
Prohibited If
Prohibited Unless
Prohibits
Regular Expression
Required
Required If
Required Unless
Required With
Required With All
Required Without
Required Without All
Required Array Keys
Same
Size
Sometimes
Starts With
String
Timezone
Unique (Database)
URL
UUID

Top comments (0)