form validation


Form validation

##Introduction

Laravel provides several different ways to validate data passed into your application. By default, Laravel's controller base classes use the

ValidatesRequests Trait, which provides a convenient way to validate incoming HTTP requests using a variety of powerful validation rules.

Quick Validation

To understand Laravel’s powerful validation capabilities, let’s look at a complete example of validating a form and displaying an error message back to the user.

Define routes

First, let us assume that in the routes/web.php file The following routes are defined in:

Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');

Obviously, 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 middle.

Create router

Let’s take a look at the controllers that handle these routes, store Leave the method blank for now.

<?php
  namespace App\Http\Controllers;
  use Illuminate\Http\Request;
  use App\Http\Controllers\Controller;
  class PostController extends Controller{    
      /**
     * 显示创建博客文章的表单。
     *
     * @return Response
     */   
  public function create()   
   {       
    return view('post.create');    
    }   
     /**
     * 保存一篇新的博客文章。
     *
     * @param  Request  $request
     * @return Response
     */   
    public function store(Request $request)   
     {      
       // 验证并存储博客文章...   
      }
   }

Writing the validator logic

Now we start writing the logic in the store method to verify new blog posts. To do this, we will use the validate method provided by the Illuminate\Http\Request object. If the verification passes, the code can run normally. If verification fails, an exception will be thrown and the corresponding error response will be automatically returned to the user. In the case of a typical HTTP request, a redirect response is generated, while for AJAX requests a JSON response is sent.

Let's go back to the store method to understand in depth the validate method:

/**
 * 保存一篇新的博客文章。
 *
 * @param  Request  $request
 * @return Response
 */
 public function store(Request $request){ 
    $validatedData = $request->validate([      
      'title' => 'required|unique:posts|max:255',        
      'body' => 'required',    
    ]);    
    // 博客文章验证通过
  }

As you can see, we will need the validation rules Passed to the validate method. Also, once again, if the verification fails, a corresponding response will be automatically generated. If the verification passes, our controller will continue to operate normally.

Stop running after the first validation failure

If you want to stop running the validation rule after a property fails validation for the first time, you need to append bail Rules to this attribute:

$request->validate([   
 'title' => 'bail|required|unique:posts|max:255',    
 'body' => 'required',
]);

In this example, if the title field does not pass the unique rule, then the program will not continue to check max rule. Rules are verified in the order they are assigned.

Note on implementation of array data

If your HTTP request contains a "nested" parameter (i.e. array), then you can pass " point" syntax to specify these parameters.

$request->validate([   
 'title' => 'required|unique:posts|max:255',    
 'author.name' => 'required',    
 'author.description' => 'required',
]);

Display validation error message

What if the incoming request parameters do not pass the given validation rules? As mentioned before, Laravel automatically redirects the user to the previous location. In addition, all verification error messages will be automatically stored in session.

Once again, we don't have to explicitly bind the error message to the view in the GET route. Because Lavarel will check the error information in the Session data and automatically bind it to the view (if the view file exists). The variable $errors is an instance of Illuminate\Support\MessageBag. For more information about this object, please consult this documentation .

{tip} $errors The variable is bound by the Illuminate\View\Middleware\ShareErrorsFromSession middleware provided by the Web middleware group into view. When this middleware is applied, the $error variable can be obtained in your view, making it always assumed that the $errors variable exists and is safe. to use.

In the above example, when validation fails, the user will be redirected to the controller's create method, allowing us to display the error message in the view:

<!-- /resources/views/post/create.blade.php -->
<h1>创建文章</h1>
@if ($errors->any())  
  <div class="alert alert-danger">     
     <ul>
       @foreach ($errors->all() as $error)                
       <li>{{ $error }}</li>
            @endforeach
      </ul>    
   </div>
 @endif
 <!-- 创建文章表单 -->

Notes about optional fields

By default, in the global middleware stack of Laravel applications The App\Http\Kernel class contains TrimStrings and ConvertEmptyStringsToNull middleware. Therefore, if you do not want the validator to treat the null value as invalid, you need to mark the "optional" request field as nullable, for example:

$request->validate([  
  'title' => 'required|unique:posts|max:255',    
  'body' => 'required',    
  'publish_at' => 'nullable|date',
]);

In this example, we specify that the publish_at field can be null or a valid date format. If the nullable modifier is not added to the rule definition, the validator will consider null to be an invalid date format.

##AJAX Request & Validation

In this example we use a traditional form to send data to the application . But in reality, many programs use AJAX to send requests. When we use the

validate method in an AJAX request, Laravel does not generate a redirect response, but instead generates a JSON response containing all validation error information. This JSON response will be sent with an HTTP status code 422.

Validation form request

Create form request verification

In the face of more complex verification scenarios, you can create a "form request" to handle more complex logic. Form requests are custom request classes that contain validation logic. You can use the Artisan command make:request to create a form request class:

php artisan make:request StoreBlogPost

The newly generated class is saved in the app/Http/Requests directory. If this directory does not exist, it will be created when running the make:request command. Let's add some validation rules to the rules method:

/**
 * 获取适用于请求的验证规则。
 *
 * @return array
 */
 public function rules(){   
  return [       
    'title' => 'required|unique:posts|max:255',        
    'body' => 'required',    
    ];
  }

{tip} You can pass in any dependencies you want to the rules method. They will be automatically resolved by the service container provided by Laravel.

How do verification rules work? All you need to do is type-hint the incoming request in the controller method. Validate the incoming form request before calling the controller method, which means you don't need to write any validation logic in the controller:

/**
 * 存储传入的博客文章。
 *
 * @param  StoreBlogPost  $request
 * @return Response
 */
 public function store(StoreBlogPost $request){   
  // 传入的请求通过验证...    
  // 获取通过验证的数据...    
  $validated = $request->validated();
 }

If validation fails, a message will be generated to return the user to the previous location redirect response. These errors will also be flashed into session so that they can be displayed on the page. If the incoming request is AJAX, an HTTP response of JSON data with a 422 status code and validation error information is returned to the user.

Add a hook after the form request

If you want to add a hook "after" the form request, you can use the withValidator method. This method accepts a complete validation constructor, allowing you to call any method before the validation result is returned:

/**
 *  配置验证器实例。
 *
 * @param  \Illuminate\Validation\Validator  $validator
 * @return void
 */
 public function withValidator($validator){ 
    $validator->after(function ($validator) {        
         if ($this->somethingElseIsInvalid()) {           
              $validator->errors()->add('field', 'Something is wrong with this field!');        
             }   
         });
   }

Form request authorization verification

The form request class also contains the authorize method. In this method, you can check the authenticated user to determine whether it has permission to update the given resource. For example, you can determine whether the user has the permission to update article comments:

/**
 * 判断用户是否有权限做出此请求。
 *
 * @return bool
 */
 public function authorize(){  
   $comment = Comment::find($this->route('comment'));    
   return $comment && $this->user()->can('update', $comment);
 }

Since all form requests inherit the request base class in Laravel, we can use the user method Get the currently authenticated logged-in user. Please also note the call to the route method in the above example. This method allows you to get the URI parameters defined on the route being called, such as the {comment} parameter in the following example:

Route::post('comment/{comment}');

If the authorize method returns false, an HTTP response containing a 403 status code will be automatically returned, and the controller method will not be run.

If you plan to handle authorization logic in other parts of the application, just return true from the authorize method:

/**
 * 判断用户是否有权限进行此请求。
 *
 * @return bool
 */
 public function authorize(){  
   return true;
  }

{ tip} You can pass any dependencies you want to the authorize method. They will be automatically resolved by the service container provided by Laravel.

Customize error messages

You can customize error messages by overriding the messages method of the form request. This method should return an array of property/rule pairs and their corresponding error messages:

/**
 * 获取已定义验证规则的错误消息。
 *
 * @return array
 */
 public function messages(){  
   return [       
    'title.required' => 'A title is required',        
    'body.required'  => 'A message is required',    
    ];
  }

##Custom Validation Properties

If you wish to replace the

:attribute portion of the validation message with a custom attribute name, you can override the attributes method to specify a custom name. This method should return an array of property/name pairs:

/**
 * 获取验证错误的自定义属性。
 *
 * @return array
 */
 public function attributes(){  
   return [      
     'email' => 'email address',    
     ];
   }

Create the validator manually

If you don't want to Using the

validate method on the request, you can manually create a validator example via the Validator facade. Create a validator example using the
make method on the Validator facade:

<?php
   namespace App\Http\Controllers;use Validator;
   use Illuminate\Http\Request;
   use App\Http\Controllers\Controller;
   class PostController extends Controller{    
      /**
     * 保存一篇新的博客文章。
     *
     * @param  Request  $request
     * @return Response
     */   
    public function store(Request $request)   
     {       
      $validator = Validator::make($request->all(), [      
            'title' => 'required|unique:posts|max:255',            
            'body' => 'required',        
          ]);       
        if ($validator->fails()) {          
          return redirect('post/create')                       
           ->withErrors($validator)                        
           ->withInput();       
           }       
       // Store the blog post...  
        }
      }

The first parameter passed to the

make method is data that needs to be verified. The second parameter is the validation rule for the data.

If verification fails, you can use the

withErrors method to flash the error message to Session. After using this method for redirection, the $errors variable will be automatically shared with the view, and you can display these messages to the user. The withErrors method receives a validator, a MessageBag or a PHP Array.

Automatic redirection

If you want to manually create a validator instance and want to use

validates method provides automatic redirection, then you can call the validate method on the existing validator example. If verification fails, the user will be automatically redirected. In an AJAX request, a JSON formatted response is returned.

Validator::make($request->all(), [   
 'title' => 'required|unique:posts|max:255',    
 'body' => 'required',
])->validate();

Named error package

If you have multiple forms on a page, you can name the error package by to retrieve the error message for a specific form. Just pass a name as the second argument to the

withErrors method

return redirect('register')          
  ->withErrors($validator, 'login');

and then you can get the error message for the specified form from the

$errors variable:

{{ $errors->login->first('email') }}

Post-validation hook

The validator also allows you to add callback functions that are allowed after successful validation so you can The next step of validation even adds more error messages to the message collection. To use it simply use the

after method on the validation instance:

$validator = Validator::make(...);$validator->after(function ($validator) {   
 if ($this->somethingElseIsInvalid()) {     
    $validator->errors()->add('field', 'Something is wrong with this field!');   
     }
   });
 if ($validator->fails()) {  
   //
 }

Handling error messages

After calling the errors method on the Validator instance, you will get an Illuminate\Support\MessageBag instance, It has various convenient methods for handling error messages. The $ errors variable automatically provided to all views and is also an instance of the MessageBag class.

View the first error message for a specific field

To view the first error message for a specific field, you can use the first method:

$errors = $validator->errors();echo $errors->first('email');

View all error messages for a specific field

If you need to get an array of all error messages for a specified field, you can use the get method:

foreach ($errors->get('email') as $message) {  
  //
}

If you want to validate an array field of a form, you can use * to get all error messages for each array element:

foreach ($errors->get('attachments.*') as $message) { 
   //
}

View All error messages for all fields

If you want to get all error messages for all fields, you can use the all method:

foreach ($errors->all() as $message) { 
   //
}

Judge specific Whether the field contains an error message

has method can be used to determine whether a given field contains an error message:

if ($errors->has('email')) { 
   //
}

Custom error message

If necessary, you can also use a custom error message instead of the default value for verification. There are several ways to specify a custom message. First, you can pass a custom message as the third parameter to the Validator::make method:

$messages = [  
  'required' => 'The :attribute field is required.',
 ];
 $validator = Validator::make($input, $rules, $messages);

In this example, the :attribute placeholder Will be replaced by the actual name of the validation field. In addition, you can use other placeholders in the verification message. 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',
];

Specify a custom message for a given property

Sometimes you may want to customize an error message only for a specific field. Just use "dot" syntax after the attribute name to specify the validation rules:

$messages = [ 
   'email.required' => 'We need to know your e-mail address!',
 ];

Specify your own rules in the language file Defining Messages

In most cases, you will probably specify custom messages in a language file rather than passing them directly to the Validator. To do this, place your message in the custom array in the resources/lang/xx/validation.php language file.

'custom' => [  
  'email' => [    
      'required' => 'We need to know your e-mail address!',  
      ],
    ],

Specify custom attributes in the language file

If you wish to replace the :attribute placeholder of the validation message with a custom attribute Name, you can specify a custom name in the attributes array of the resources/lang/xx/validation.php language file:

'attributes' => [  
  'email' => 'email address',
 ],

Specifying custom values ​​in language files

Sometimes it may be necessary to replace the :value placeholder of the validation message with a custom literal for the value. For example, if the value of payment_type is cc, use the following validation rule, which specifies that a credit card number is required:

$request->validate([  
  'credit_card_number' => 'required_if:payment_type,cc'
 ]);

If this validation rule fails, the following results Error message:

    当payment type为cc时,credit card number 不能为空。

You can specify a custom value representation in the validation language file by defining the values array instead of displaying cc As payment type value:

'values' => [ 
   'payment_type' => [    
       'cc' => '信用卡' 
        ],
    ],

Now, if the validation rule fails, it will produce the following message:

    当payment type 为信用卡时,credit card number不能为空。

##

可用验证规则

以下是所有可用验证规则及其功能的列表:

accepted

The validation field must be yes, on, 1, or true. This is useful when confirming whether you agree with the Terms of Service.

active_url

According to the PHP function dns_get_record, the validation field must have a valid A or AAAA record.

after:date

The validation field must be a value after the given date. The date value will be passed to the PHP function strtotime:

'start_date' => 'required|date|after:tomorrow'

Instead of passing the date to be processed by strtotime you can specify another field to compare with the date String:

'finish_date' => 'required|date|after:start_date'

after_or_equal:date

The validation field must be in the given A value after or the same as this date. See the after rules for more information.

alpha

The validation field must consist entirely of letters.

alpha_dash

Validation fields may contain letters, numbers, as well as dashes (-) and underscores (_).

alpha_num

The validation field must be entirely letters and numbers.

array

The field to be validated must be a PHP array.

bail

Stop running validation rules after the first validation failure.

before:date

The validation field must be before the given date. This date value will be passed to PHP’s strtotime function for calculation.

##before_or_equal:

date

The validation field must be before or with the given date the same date. This date value will be passed to PHP’s

strtotime function for calculation.

between:

min,max

Validation fields The size must be between the given

min and max. Strings, numbers, arrays and files are calculated using the size method.

boolean

The field to be validated must be convertible to Boolean type. Acceptable inputs are true, false, 1, 0, "1", and "0".

confirmed

The validation field must have matching field foo_confirmation. For example, if the validation field is password , a matching password_confirmation field must exist in the input.

date

According to the PHP function strtotime, the validation field must be a valid date.

date_equals:date

Validation field must be equal to the given date. The date will be passed to the PHP function strtotime.

date_format:format

The validation field must match the given date format. When validating a field, you should only use date or date_format, not both.

##different:

field

The validation field must have the same value as

field Different values.

##digits:
value

The validation field must be

numeric

, and must have the exact length of _value_.

digits_between:
min

,maxVerified fields The length must be between the given

min

and max.

dimensions

The file under verification must be an image and comply with the specified rule constraints:

'avatar' => 'dimensions:min_width=100,min_height=200'

The available constraints are:

min_width

, max_width, min_height, max_height, width, height, ratio.

ratio

The limit should be expressed as width divided by height. This can be specified by using an expression like 3/2 or a floating point number like 1.5:

'avatar' => 'dimensions:ratio=3/2'
Since this rule requires multiple arguments, you can Use the

Rule::dimensions

method to construct rules fluently:

use Illuminate\Validation\Rule;
Validator::make($data, [  
  'avatar' => [     
     'required',        
     Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),    
   ],
  ]);

distinct

When When validating an array, the validation fields must not contain any duplicate values.

'foo.*.id' => 'distinct'

email

The validation field must be a properly formatted email address.

exists:table,column

Validate fields must exist in the given database table.

Exists Basic Rule Usage

'state' => 'exists:states'

If the column option is not specified, the field name will be used.

Specify custom table fields

'state' => 'exists:states,abbreviation'

Sometimes, you may need to specify a specific database connection to be used for "exists" queries. You can do this by adding the connection name to the table name using "dot" syntax:

'email' => 'exists:connection.staff,email'

If you want to customize the query executed by the validation rule, you can use the Rule class Fluently define rules. In the following example, we also specify the validation rules as an array instead of using the | characters to separate them:

use Illuminate\Validation\Rule;
Validator::make($data, [  
  'email' => [      
    'required',        
    Rule::exists('staff')->where(function ($query) {  
           $query->where('account_id', 1);    
        }),
     ],
  ]);

file

The fields to be verified must be successfully uploaded files.

filled

The validation field must not be empty when present.

##gt:

field

The validation field must be greater than the given

field . Both fields must be of the same type. Strings, numbers, arrays, and files are all evaluated identically using size.

##gte:
field

Validation field must be greater than or equal to the given

field

. Both fields must be of the same type. Strings, numbers, arrays, and files are all evaluated identically using size.

image

The file to be verified must be an image (jpeg, png, bmp, gif, or svg)

in:
foo

,bar,... The validation field must be contained in the given list of values. Since this rule typically requires you to

implode

an array, you can use the Rule :: in method to construct the rule fluently:

use Illuminate\Validation\Rule;
Validator::make($data, [  
  'zones' => [      
    'required',        
    Rule::in(['first-zone', 'second-zone']),  
   ],
]);

in_array:
anotherfield

The field being validated must exist within the value of another field

anotherfield

.

integer

The field to be verified must be an integer.

ip

The field to be verified must be the IP address.

ipv4

The field to be verified must be an IPv4 address.

ipv6

The field to be verified must be an IPv6 address.

json

The fields to be verified must be valid JSON strings.

lt:field

The field under validation must be smaller than the given field. Both fields must be of the same type. String, numeric, array, and file sizes are calculated and evaluated with the size method.

##lte:

field

The field under validation must be less than or equal to the given

Field. Both fields must be of the same type. String, numeric, array, and file sizes are calculated and evaluated with the size method.

max:

value

Fields under validation must be less than or equal to

value. String, number, array or file size calculations are evaluated using the size method.

##mimetypes:
text/plain

,...The file to be verified must be the same as Matches one of the given MIME types:

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

To determine the MIME type of an uploaded file, the contents of the file are read to determine the MIME type, which may differ from the MIME type provided by the client.

##mimes:
foo
,

bar,...The file being verified must have a MIME type corresponding to one of the listed extensions.

Basic usage of MIME rules
'photo' => 'mimes:jpeg,bmp,png'
Even though you may only need to verify the specified extension, this rule actually verifies the MIME type of the file by reading the file content to guess its MIME type.

A complete list of MIME types and their corresponding extensions can be found at the following link:

https://svn.apache.org/repos/asf/httpd/htt...


min:
value

The field under validation must have a minimum value. String, number, array or file size calculations are evaluated using the

size

method.

##not_in:

foo
,
bar

,...The field being validated cannot be included in the given list of values. The Rule::notIn method can be used to build rules:

use Illuminate\Validation\Rule;
Validator::make($data, [  
  'toppings' => [     
     'required',        
     Rule::notIn(['sprinkles', 'cherries']), 
     ],
 ]);

not_regex:pattern

The fields under validation must not match the given regular expression.

Internally, this rule uses the PHP preg_match function. The value entered should follow the same format required by the preg_match function, so include valid delimiters as well. For example: 'email' => 'not_regex:/^. $/i'.

Note: When using the regex/not_regex pattern it may be necessary to specify the rules in an array rather than using pipe delimiters, esp. This is when the regular expression contains pipe characters.

nullable

The verified field can be null. This is particularly useful when validating basic data types, such as strings and integers, which can contain null values.

numeric

The field to be validated must be numeric.

present

The field being validated must exist in the input data, but can be empty.

regex:pattern

The field to be validated must match the given regular expression match.

Internally, this rule uses the PHP preg_match function. The value entered should follow the same format required by the preg_match function, so include valid delimiters as well. For example: 'email' => 'regex:/^. @. $/i'.

Note: When using regex rules, you must use arrays instead of using | delimiters, especially if the regex Contains | characters.

required

The field to be validated must exist in the input data and not be empty. A field is considered "null" if one of the following conditions is met:

  • The value is null.
  • The value is an empty string.
  • The value is an empty array or an empty Countable object.
  • The value is an uploaded file without a path.

##required_if:

anotherfield,value,.. .

If the

anotherfield field is equal to any value, the field being validated must be present and not empty.

If you want to construct a more complex condition for the

required_if rule, you can use the Rule::requiredIf method. This method accepts a boolean value or closure. When passing a closure, true or false should be returned to confirm whether the field needs to be validated:

use Illuminate\Validation\Rule;
Validator::make($request->all(), [  
  'role_id' => Rule::requiredIf($request->user()->is_admin),]);
  Validator::make($request->all(), [   
   'role_id' => Rule::requiredIf(function () use ($request) {     
      return $request->user()->is_admin;   
      }),
    ]);

required_unless:anotherfield,value,...

If anotherfield field is not equal to any value , the field to be verified must be present and not empty.

##required_with:

foo,bar,...

The verified field must appear and not be empty only when any other specified field appears.

##required_with_all:
foo

,bar,...Only when all other specified fields appear, the verified field must appear and not be empty.

##required_without:
foo
,

bar,...Only when any other specified field does not appear, the verified field must appear and not be empty.

##required_without_all:

foo
,
bar

,...Only when all other specified fields do not appear, the verified field must appear and not be empty.

same:

field

The field being validated must match the given field.

size:

value

The field being validated must have a value that matches the given value size. For strings, value corresponds to the number of characters. For numbers, value corresponds to the given integer value. For arrays, size corresponds to the count value of the array. For files, size corresponds to the file size in kb.

##starts_with:foo

,
bar
,...

The field to be validated must start with one of the given values.

string

The field to be verified must be a string. If this field is allowed to be
null
, the

nullable

rule needs to be assigned to this field.

timezone

The field to be verified must be a valid time zone based on the PHP function
timezone_identifiers_list
logo.

unique:table,column,except,idColumn

The fields to be verified are in the given database Must be unique in the table. If column is not specified, the name of the field itself will be used.

Specify custom fields

'email' => 'unique:users,email_address'

Custom database connection

Sometimes, you may need to create a database for the validator Query settings for custom connections. In the above example, setting unique:users as the validation rule is equivalent to using the default database connection to query the database. If you want to modify it, please use the "dot" method to specify the connection and table name:

'email' => 'unique:connection.users,email_address'

Force the Unique rule to ignore the specified ID:

Sometimes, you may want to Ignore the specified ID when verifying field uniqueness. For example, the "Update Profile" page will include your username, email address, and location. At this point you will want to verify that the updated email value is unique. If the user only changes the username field but not the email field, there is no need to throw a validation error because the user is already the owner of the email.

Use the Rule class to define rules to instruct the validator to ignore the user's ID. This example specifies validation rules as an array, rather than using | characters to separate them:

use Illuminate\Validation\Rule;
Validator::make($data, [ 
   'email' => [      
     'required',        
     Rule::unique('users')->ignore($user->id),  
     ],
 ]);

{tip} You should never pass any user-controlled request input to ignore method. Instead, you should only pass system-generated unique IDs, such as auto-increment IDs or UUIDs, from Eloquent model instances. Otherwise, your application will be vulnerable to SQL injection attacks.

Instead of passing the value of a model key to the ignore method, you can pass the entire model instance. Laravel will automatically extract the primary key from the model:

Rule::unique('users')->ignore($user)

If the primary key name used by your data table is not id, then specify the field when calling the ignore method Name:

Rule::unique('users')->ignore($user->id, 'user_id')

By default, the unique rule checks whether columns matching the name of the property being validated are unique. But you can pass a different column name as the second argument to the unique method:

Rule::unique('users', 'email_address')->ignore($user->id),

Add an additional Where statement:

you Additional query conditions can also be specified through the where method. For example, we add account_id to the constraint of 1:

'email' => Rule::unique('users')->where(function ($query) {  
  return $query->where('account_id', 1);
})

##url

The field to be verified must be a valid URL.

uuid

The validation field must be valid RFC 4122 (version 1,3,4 or 5) generic Unique identifier (UUID).

Add rules based on conditions

Validate if exists

In some cases, validation checks can only be performed on a field if it exists in the array. This can be achieved by adding sometimes to the rule list:

$v = Validator::make($data, [    'email' => 'sometimes|required|email',]);

In the above example, the email field only exists in the $data array will be verified.

{tip} If you are trying to validate a field that should always be present but may be empty, please review Notes on Optional Fields

Complex conditional validation

Sometimes you may need to add validation rules based on more complex conditional logic. For example, you might want a specified field to be required only if the value of another field exceeds 100. Or when a specified field exists, the other two fields can have the given value. Adding such verification conditions is not difficult. First, create a Validator instance using a static rule:

$v = Validator::make($data, [  
  'email' => 'required|email',    
  'games' => 'required|numeric',
]);

Let’s say we have a web application designed for game collectors. If a game collector has more than a hundred games, we'd like them to explain why they own so many games. For example, they might run a game distribution store, or just enjoy collecting. To include this validation requirement under certain conditions, you can use the sometimes method on the Validator instance.

$v->sometimes('reason', 'required|max:500', function ($input) {  
  return $input->games >= 100;
});

Pass in the first parameter of the sometimes method is the name of the field to be used for verification. The second parameter is the validation rule we want to use. Closure is passed in as the third parameter. If it returns true, additional rules will be added. This method makes it easy to create complex conditional validations. You can even add conditional validation to multiple fields at once:

$v->sometimes(['reason', 'cost'], 'required', function ($input) {   
   return $input->games >= 100;
 });

{tip} The $input parameter passed into the closure is Illuminate An instance of \Support\Fluent that can be used to access your input or file objects.

Validate Array

It is not difficult to verify that the input of the form is an array field. You can use the "dot" method to validate properties in an array. For example, if the incoming HTTP request contains the photos[profile] field, it can be verified as follows:

$validator = Validator::make($request->all(), [  
  'photos.profile' => 'required|image',
]);

You can also verify each element in the array. For example, to verify that each email in the specified array input field is unique, you can do this:

$validator = Validator::make($request->all(), [  
  'person.*.email' => 'email|unique:users',    
  'person.*.first_name' => 'required_with:person.*.last_name',
]);

Similarly, you can use the * characters when defining verification information in the language file, Use a single validation message for array-based fields:

'custom' => [  
  'person.*.email' => [    
      'unique' => 'Each person must have a unique e-mail address',   
     ]
    ],

Custom validation rules

Using Rule Objects

Laravel provides many useful validation rules; it also supports custom rules. One way to register custom validation rules is to use a rule object. You can use the Artisan command make:rule to generate new rule objects. Next, let's use this command to generate a rule that validates that a string is uppercase. Laravel will store new rules in the app/Rules directory:

php artisan make:rule Uppercase

Once the rule is created, we can define its behavior. The rule object contains two methods: passes and message. The passes method receives the attribute value and name, and returns true or false depending on whether the attribute value conforms to the rules. The message method should return the validation error message that should be used if validation fails:

<?php
  namespace App\Rules;
  use Illuminate\Contracts\Validation\Rule;
  class Uppercase implements Rule{   
        /**
     * 判断验证规则是否通过。
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */   
    public function passes($attribute, $value)   
     {       
       return strtoupper($value) === $value;   
      }   
     /**
     * 获取验证错误消息。
     *
     * @return string
     */   
    public function message()  
      {       
       return 'The :attribute must be uppercase.';   
       }
      }

Of course, if you wish to return an error message from the translation file, you can do so from message Call the helper function in the method trans:

/**
 * 获取验证错误消息。
 *
 * @return string
 */
 public function message(){  
   return trans('validation.uppercase');
  }

Once the rule object is defined, you can pass an instance of the rule object to the validator along with other validation rules:

use App\Rules\Uppercase;$request->validate([  
  'name' => ['required', 'string', new Uppercase],
]);

Using Closures

If you only need the functionality of a custom rule once in your application, you can use Closures instead of rule objects. The closure receives the name of the property, the value of which should be used if validation fails $fail in the callback:

$validator = Validator::make($request->all(), [   
 'title' => [      
   'required',        
   'max:255',        
   function ($attribute, $value, $fail) {          
     if ($value === 'foo') {              
       $fail($attribute.' is invalid.');      
             }      
            },    
          ],
        ]);

Using extensions

Another way to register custom validation rules is to use the extend method in the Validator facade. Let's use this method in the service container to register custom validation rules:

<?php
  namespace App\Providers;
  use Illuminate\Support\ServiceProvider;
  use Illuminate\Support\Facades\Validator;
  class AppServiceProvider extends ServiceProvider{   
      /**
     * 引导任何应用程序。
     *
     * @return void
     */   
  public function boot()   
   {       
     Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { 
        return $value == 'foo';  
         });   
       }    
     /**
     * 注册服务提供器。
     *
     * @return void
     */   
     public function register()   
      {       
       //   
       }
     }

The custom validation closure receives four parameters: the attribute name to be validated $attribute, attribute The value $value, the parameter array $parameters passed into the validation rule, and the Validator actual column.

In addition to using closures, you can also pass in classes and methods to the extend method:

Validator::extend('foo', 'FooValidator@validate');

Define error messages

You also need to define error messages for custom rules. You can achieve this functionality using an inline custom message array or by adding an entry in the validation language file. The message should be placed first in the array, not in the custom array that is only used to store attribute-specific error messages:

"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// 其余的验证错误消息...

When creating a custom validation rule, you There may be times when you need to define custom placeholders for error messages. This can be done by creating a custom validator and then calling the Replacer method on the Validator facade. You can perform the following operations in the boot method of the service container:

/**
 * 启动应用程序。
 *
 * @return void
 */
 public function boot(){  
   Validator::extend(...);    
   Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {    
       return str_replace(...);  
      });
 }

Implicit expansion

By default, when the attribute to be validated does not exist or contains a null value defined by the required rule, then normal validation Rules, including custom extensions will not be executed. For example, the unique rule will not verify the null value:

$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes();
 // true

This is necessary if you require that the property be verified even if it is null The hint attribute is required. To create such an "implicit" extension, you can use the Validator::extendImplicit() method:

Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) { 
   return $value == 'foo';
  });

{note} "Implicit" extension only implies that the property is required of. Whether it's missing or null is up to you.

This article was first published on the LearnKu.com website.