Laravel implements scene verification rules based on FormRequest

Posted Jun 29, 20204 min read

Overview

In the development process, we often encounter the need for form verification. Laravel provides us with a powerful and extensible validator so that we can quickly achieve such requirements, but because Laravel does not provide us with similar to yii2 Scene concept, which makes us want to
Requests with verification rules all create a request class file, or write the verification rules directly in the controller. This may sound no problem, but in actual development we encounter very complex business scenarios, which need to provide hundreds or thousands of interfaces, that is to say, to create hundreds or thousands of request file or hundreds or thousands of The verification rules are written in the controller.

In order to solve this problem, refer to yii2 scene , try to implement the concept of scene in Laravel, but Laravel is very different. The Requst class that is automatically verified in Laravel is injected, so that when you want to implement automatic verification, you have already used the correct scene unless you carry the scene parameters when you submit through the form or try to use Middleware for processing However, these two methods are not ideal. After a period of trial and thought, I thought that variable names can be used to transfer scene information.

So I started to realize it, I thought it was a good solution, I can easily get the name of the instantiated class inside the class through the built-in function or magic function or the reflection class. As a result, I wasted a long and long time here and tried many ways. , But there is still no way to get the instance name. When it was almost time to give up. I tried to get the controller class to be reached through Laravel routing, and then get the variable name through the reflection class.

installation

composer require laravel-form-request/laravel-form-request

Doc

Form request base class source code test case

The form request base class is an abstract class and cannot be instantiated directly. All request classes that need to use the scene need to inherit this class.

The form request base class inherits from Laravel's form request class. The following methods are decorated with the final keyword and cannot be rewritten. You need to use the scene name + method name camel case to rewrite to achieve different scenarios using different verification rules.

  • authorize()
  • rules()
  • messages()
  • attributes()

The form request base class provides the following rewrite method for the above method to use the default scenario. You need to rewrite your own rules after inheritance.

  • defaultAuthorize()
  • defaultRules()
  • defaultMessages()
  • defaultAttributes()

The default scene of the form request base class is default. You can use const SCENARIO_DEFAULT ='login' in the subclass to modify the default scene name. The form request base class provides the following methods to obtain and reset the scene

  • getScenario()
  • setScenario(string $scenario)

The form request base class rewrites the prepareForValidation method of the Laravel form request class to implement the interception request class variable name as a scene. The prepareForValidation method is also decorated with the final keyword and cannot be rewritten. The main functions are implemented through Laravel's routing, so if the request is not built through routing, this function cannot be used.
The form request base class uses Request to intercept variables by default. For example, the scene name intercepted by $defaultRequest is default. You can use protected $delimiter ='_request'; in the subclass to modify the default delimiter.

The following uses the user's form request class as an example to introduce the use of scenarios. Three scenarios are defined in the following definitions, which are the default index closure

use LaravelFormRequest\FormRequest;
class UserFormRequest extends FormRequest
{
    public function defaultRules()
    {
        return [];
    }
    public function defaultMessages()
    {
        return [];
    }
    public function indexRules()
    {
        return [
            'name' =>'required',
       ];
    }
    public function indexMessages()
    {
        return [
            'name.required' =>'The name field is required in index scenario.',
       ];
    }
    public function closureRules()
    {
        return [
            'name' =>'required',
       ];
    }
    public function closureMessages()
    {
        return [
            'name.required' =>'The name field is required in closure scenario.',
       ];
    }
}

Then use the same request class to define in the controller, before the request reaches the controller, it will be converted into different scene rules according to the variable name for verification

use Illuminate\Routing\Controller as BaseController;
class UserController extends BaseController
{
    public function index(UserFormRequest $request)
    {
        echo $request->getScenario(); //default
    }
    public function index(UserFormRequest $indexRequest)
    {
        echo $indexRequest->getScenario(); //index
    }
}

You can also use the form of routing closure for verification without using a controller

Route::get('users', function(UserFormRequest $closureRequest) {
    echo $closureRequest->getScenario(); //closure
});