Laravel method and problem summary _php techniques used in formrequest

Source: Internet
Author: User
Tags error handling exception handling mixed

In ' Laravel ', each request is encapsulated as a ' request ' object, and the ' Form request ' object is a custom ' request ' class that contains additional validation logic (and access control). In this paper, the processing process of formrequest anomaly is analyzed and the idea of formrequest verification failure is proposed.

All samples are based on Laravel 5.1.39 (LTS)

It's a nice day today, let's talk about form validation.

Make form verification in controller

Some students write form validation logic in controller, such as the validation of user submissions:

<?php

//... 

Use Validator;

Class Commentcontroller
{public

  function poststorecomment (Request $request)
  {
    $validator = Validator::make ($request->all (), [
      ' comment ' => ' required ',//is just an example, write a simple rule, your site if so write welcome in the comments posted URL
    ]);

    if ($validator->fails ()) {return
      redirect ()
        ->back ()
        ->witherrors ($validator)
        -> Withinput ();
    }
  

In this case, form validation and business logic are crammed together, we have too much code in our controller, and duplicate validation rules are basically copy and paste.

We can use form request to encapsulate form validation code, thus streamlining the code logic in controller to focus on the business. The independent form validation logic can even be reused in other requests, such as modifying comments.

What is form Request

In Laravel, each request is encapsulated as a requests object, and the Form request object is a custom request class that contains additional validation logic (and access control).

How to use form request to do form validation

Laravel provides the artisan command to generate form request:

<code>$ PHP Artisan make:request storecommentrequest</code>

So it generates the app/http/requests/storecommentrequest.php, let's analyze the content:

<?php

namespace app\http\requests;

Use App\http\requests\request; As you can see, this base class is in our project, which means we can modify it

class Storecommentrequest extends Request
{
  /**
   * determine if the The user is authorized to make this request.
   *
   * @return bool
  /Public Function authorize ()//This method can be used to control access rights, such as prohibiting unpaid user comments ...
  {return
    false;//Note! This defaults to False, and is remembered to be true
  }

  /** * Get the validation rules which apply to the
   request.
   *
   * @return Array
  /Public Function rules ()//This method returns an array of validation rules, that is, the validator validation rule
  {return
    [
      //
    ];
  }
}

So it's easy to let the rules method return our validation rules in addition to having the authorize method return true:

<?php

//...

  Public function rules ()
  {return
    [

    ];
  }

// ...

And then revise our controller:

<?php

//...

  Before: Public function poststorecomment (Request $request) public
  function Poststorecomment (\app\http\requests\ Storecommentrequest $request)
  {
    //...
  }

// ...

This laravel automatically invokes the Storecommentrequest for form validation.

Exception handling

If the form validation fails, Laravel redirects to the previous page and writes the error to the session and, if it is an AJAX request, returns a section of JSON data with an HTTP status of 422, similar to this:

<code>{comment: ["The comment field is required."]} </code>

Here is not to elaborate on how to modify the information, if someone want to see the relevant tutorials, you can leave a message.

We mainly talk about how to customize error handling.

In general, errors in Laravel are exceptions (Exception), and we can all handle them uniformly in app\exceptions\handler.php. The Form request does throw a illuminate\http\exception\httpresponseexception exception, but the exception is handled specifically in the routing logic.

First, let's look at how the form request was executed:

Illuminate\validation\validationserviceprovider:

<?php

namespace Illuminate\validation;

Use Illuminate\support\serviceprovider;
Use illuminate\contracts\validation\validateswhenresolved;

Class Validationserviceprovider extends serviceprovider
{
  /**
   * Register the service provider.
   *
   * @return void
   *
  /Public Function register ()
  {
    $this->registervalidationresolverhook ( ); Look at me I see I

    $this->registerpresenceverifier ();

    $this->registervalidationfactory ();
  }

  /**
   * Register the "validateswhenresolved" container hook.
   *
   * @return void
   /
  protected function Registervalidationresolverhook ()//Yes, that's me.
    Here you can see the implementation of ' validateswhenresolved ' to do a listening
    $this->app->afterresolving (function validateswhenresolved $ Resolved) {
      $resolved->validate ();//Then called its ' validate ' method for validation
    });

// ...

You guessed it, the Form request implemented this illuminate\contracts\validation\validateswhenresolved interface:

<?php 

namespace Illuminate\foundation\http;

Use Illuminate\http\request;
Use Illuminate\http\response;
Use Illuminate\http\jsonresponse;
Use Illuminate\routing\redirector;
Use Illuminate\container\container;
Use Illuminate\contracts\validation\validator;
Use illuminate\http\exception\httpresponseexception;
Use illuminate\validation\validateswhenresolvedtrait;
Use illuminate\contracts\validation\validateswhenresolved; Is you use
illuminate\contracts\validation\factory as validationfactory;

We ' App\http\requests\request ' is inherited from this ' Formrequest ' class
Formrequest extends Request implements Validateswhenresolved//Is you
{use
  validateswhenresolvedtrait;//This we'll have to see later

  .

The Validate method in the Formrequest base class is implemented by this illuminate\validation\validateswhenresolvedtrait:

Illuminate\validation\validateswhenresolvedtrait:

<?php

namespace Illuminate\validation;

Use illuminate\contracts\validation\validationexception;
Use illuminate\contracts\validation\unauthorizedexception;

/**
 * Provides default implementation of validateswhenresolved contract.
 * *
trait validateswhenresolvedtrait
{
  /**
   * Validate the class instance.
   *
   * @return void
  /Public Function validate ()///Here implements the ' validate ' method
  {
    $instance = $this-> Getvalidatorinstance (); This gets the ' Validator ' instance

    if (! $this->passesauthorization ()) {
      $this->failedauthorization ();// This is the failed process that invoked the access authorization
    } elseif (! $instance->passes ()) {
      $this->failedvalidation ($instance); Here we call the validation failed processing, we mainly look here
    }

  //...

In validate, if the validation fails, the $this->failedvalidation () is invoked and continues:

Illuminate\foundation\http\formrequest:

<?php

//...

  /**
   * Handle a failed validation attempt.
   * *
   @param \illuminate\contracts\validation\validator $validator
   * @return mixed
   /
  protected function failedvalidation (Validator $validator)
  {
    throw new Httpresponseexception ($this->response (// This throws out the legendary anomaly
      $this->formaterrors ($validator))
    );
  

Finally see the anomaly! But this anomaly was dealt with in another place:

Illuminate\routing\route:

<?php

  //...

  /**
   * Run the route action and return the response.
   * *
   @param \illuminate\http\request $request
   * @return Mixed * * Public
  function run (Request $request) c9/>{
    $this->container = $this->container?: New Container;

    try {
      if (! is_string ($this->action[' uses ')) {return
        $this->runcallable ($request);
      }

      if ($this->customdispatcherisbound ()) {return
        $this->runwithcustomdispatcher ($request);
      }

      return $this->runcontroller ($request);
    } catch (Httpresponseexception $e) {//This is where
      return $e->getresponse ();//Here directly returns response to the client
    }
  }

  // ...

So far, the whole idea is clear, but let's see how the response in the httpresponseexception exception generated here:

Illuminate\foundation\http\formrequest:

<?php

//...

  132 Lines:
  if ($this->ajax () | | $this->wantsjson ()) {//Processing of AJAX requests return to
    new Jsonresponse ($errors, 422); c5/>}

  return $this->redirector->to ($this->getredirecturl ())//processing of normal form submissions
                  ->withinput ($this- >except ($this->dontflash))
                  ->witherrors ($errors, $this->errorbag);

// ...

I'm sure you've read it.

How to implement custom error handling, here are two ideas that need to rewrite App\http\requests\request's failedvalidation:

Throws a new exception, inherits the Httpresponseexception exception, the realization GetResponse method, this exception class we may put under the app/exceptions/to be easy to manage, the error return still gives Laravel;

Throws a custom exception, which is handled in the App\exceptions\handler.

Concrete implementation Here is not written (refer to the Error handling section of the Laravel documentation, Chinese document portal), if you have other methods or ideas can be in the comments and communicate with me.

Add

If your controller is validated using the Validate method of illuminate\foundation\validation\validatesrequests this trait, the same Validation failures here also throw illuminate\http\exception\httpresponseexception exceptions, which can be referred to above solutions for processing.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.