HTTP Routing


1. Basic route

All application routes are defined in App\Providers\RouteServiceProvider Class loaded app/Http/routes.php File. The most basic Laravel route receives a URI and a closure:

 Route::get('foo', function () { return 'Hello World'; }); Route::post('foo', function () { // });

By default, routes.php The file contains a single route and a routing group. All routes contained in this routing group use middleware groups web This middleware group provides session status and CSRF protection functions for routing. Generally, we will define all routes in this routing group.

Effective routing method

We can register a route to respond to any HTTP request:

 Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback);

Sometimes you need to register a route to respond to multiple HTTP requests - this can be done through match Method. Or, you can even use any Method registers a route to respond to all HTTP requests:

 Route::match(['get', 'post'], '/', function () { // }); Route::any('foo', function () { // });

2. Routing parameters

Required parameter

Sometimes we need to capture URI fragments in the route. For example, to capture a user ID from a URL, you need to define routing parameters in the following way:

 Route::get('user/{id}', function ($id) { return 'User '.$id; });

You can define multiple route parameters in the route as needed:

 Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) { // });

Route parameters are always wrapped in curly braces. These parameters will be passed to the route closure when the route is executed.

Note: Route parameters cannot include - Character, can be used if necessary _ replace.

Optional parameters

Sometimes you may need to specify optional routing parameters. This can be done by adding a ? Mark. In this case, you need to specify default values for the corresponding variables:

 Route::get('user/{name?}', function ($name = null) { return $name; }); Route::get('user/{name?}', function ($name = 'John') { return $name; });

Regular constraint

You can use the where Method to constrain the format of routing parameters. where Method receives a parameter name and a regular expression to define how the parameter is constrained:

 Route::get('user/{name}', function ($name) { // })->where('name', '[A-Za-z]+'); Route::get('user/{id}', function ($id) { // })->where('id', '[0-9]+'); Route::get('user/{id}/{name}', function ($id, $name) { // })->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
Global constraints

If you want the routing parameters to be constrained by a given regular expression in the global scope, you can use pattern method. stay RouteServiceProvider Class boot Define the constraint mode in the method:

 /** *Define routing model binding, mode filter, etc * * @param  \Illuminate\Routing\Router  $router * @return void * @translator   https://xueyuanjun.com */ public function boot(Router $router){ $router->pattern('id', '[0-9]+'); parent::boot($router); }

Once the mode is defined, it will be automatically applied to all routes containing the parameter name:

 Route :: get ( 'user/{id}' ,  function  ( $id )  {
    //Only when {id} is a number can it be called } ) ;

3. Named Routes

Named routes facilitate the generation of URLs or redirects. The implementation is also very simple. Use array keys when defining routes as Specify route name:

 Route::get('user/profile', ['as' => 'profile', function () { // }]);

In addition, you can specify a routing name for controller actions:

 Route::get('user/profile', [ 'as' => 'profile', 'uses' => ' UserController@showProfile ' ]);

In addition to specifying the route name in the route array definition, you can also use the name Method chain:

 Route::get('user/profile', ' UserController@showProfile ')->name('profile');

Routing group&named route

If you are using a routing group, you can specify it in the attribute array of the routing group as Keyword to set a common routing name prefix for routes in the group:

 Route::group(['as' => 'admin::'], function () { Route::get('dashboard', ['as' => 'dashboard', function () { //The route is named "admin:: dashboard" }]); });

Generate URLs for named routes

If you name a given route, you can use the route The function generates the corresponding URL for the named route:

 $url = route('profile'); $redirect = redirect()->route('profile');

If the named route defines a parameter, it can be passed as the second parameter to route Function. The given route parameters will be automatically inserted into the URL:

 Route::get('user/{id}/profile', ['as' => 'profile', function ($id) { // }]); $url = route('profile', ['id' => 1]);

4. Routing group

Routing groups allow us to share routing attributes, such as middleware and namespace, among multiple routes, so that we do not have to define attributes for each route separately. The shared attribute is passed as the first parameter to the Route::group method.

Next, we will demonstrate routing groups through several simple application examples.

middleware

To assign middleware to all routes defined in the routing group, you can use it in the group attribute array middleware Middleware will be executed in the order defined in the array:

 Route::group(['middleware' => 'auth'], function () { Route::get('/', function () { //Use Auth middleware }); Route::get('user/profile', function () { //Use Auth middleware }); });

Namespace

Another common example is that routing groups assign the same PHP namespace to multiple controllers under it, which can be used in the group attribute array namespace To specify the common namespace of all controllers in the group:

 Route::group(['namespace' => 'Admin'], function(){ //The controller is under the "App  Http  Controllers  Admin" namespace Route::group(['namespace' => 'User'], function(){ //The controller is under the namespace "App  Http  Controllers  Admin  User" }); });

By default, RouteServiceProvider introduce routes.php And specify the default namespace of all controller classes under it App\Http\Controllers Therefore, we only need to specify the namespace when defining App\Http\Controllers The following part is enough.

Subdomain routing

The routing group can also be used for the routing wildcard of the sub domain name. The sub domain name can be assigned to the routing parameters like the URI, which allows capturing the part of the sub domain name for routing or controller. The sub domain name can be used for routing or controller through the domain To specify:

 Route::group(['domain' => '{account}.myapp.com'], function () { Route::get('user/{id}', function ($account, $id) { // }); });

Routing prefix

group properties prefix It can be used to add a given URI prefix for each route in the group. For example, you can add all route URIs admin Prefix:

 Route::group(['prefix' => 'admin'], function () { Route::get('users', function () { //Match "/admin/users" URL }); });

You can also use prefix Parameters Specify public routing parameters for routing groups:

 Route::group(['prefix' => 'accounts/{account_id}'], function () { Route::get('detail', function ($account_id) { //Match accounts/{account_id}/detail URL }); });

5. CSRF attack

brief introduction

Cross site request forgery is a malicious vulnerability that exploits credit websites by masquerading the requests of authorized users. Laravel makes it easy to prevent applications from being attacked by cross site request forgery.

Larvel automatically generates a CSRF "token" for each valid user session managed by the application. The token is used to verify whether the authorized user and the initiator are the same person. To generate a hidden input field containing a CSRF token, you can use the help function csrf_field To achieve:

 <? php echo csrf_field(); ?>

auxiliary function csrf_field The following HTML will be generated:

 <input type="hidden" name="_token" value="<?php echo csrf_token(); ?> ">

Of course, you can also use the methods provided by the Blade template engine:

 {!! csrf_field() !!}

You don't need to write your own code to verify the CSRF token requested by POST, PUT or DELETE, because Larvel has its own HTTP middleware VerifyCsrfToken Will do this for us: token Value and stored in Session token Make comparison to verify.

Exclude specified URL from CSRF protection

Sometimes we need to exclude some URLs from CSRF protection. For example, if you use Stripe to process payment and use their webhook system, then you need to exclude webhook processor routing from Laravel's CSRF protection.

To achieve this, you need to VerifyCsrfToken Add the URL to be excluded to $except Properties:

 <? php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfToken extends BaseVerifier { /** *URLs excluded from CSRF validation * * @var array */ protected $except = [ 'stripe/*', ]; }

X-CSRF-Token

In addition to verifying the CSRF token as a POST parameter, you can also set the X-CSRF-Token The request header is used for verification, VerifyCsrfToken Middleware will check X-CSRF-TOKEN In the request header, first create a meta tag and save the token to the meta tag:

 <meta name="csrf-token" content="{{ csrf_token() }}">

Then add the token to all request headers in the js library (such as jQuery), which provides a simple and convenient way for AJAX based applications to avoid CSRF attacks:

 $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });

X-XSRF-Token

Laravel also saved the CSRF token to a file named XSRF-TOKEN In the cookie, you can use the cookie value to set X-XSRF-TOKEN Request header. Some JavaScript frameworks, such as Angular, will automatically set this value for you. Basically, you don't need to set this value manually.

6. Routing model binding

Larave routing model binding provides convenience for injecting class instances to routes. For example, you can inject the entire User class instance matching the given ID into routes instead of directly injecting user IDs.

Implicit binding

Laravel will automatically resolve Eloquent model type declarations defined in route or controller actions (variable names match route fragments), such as:

 Route::get('api/users/{user}', function (App\User $user) { return $user->email; });

In this example, because the type declares the Eloquent model App\User , corresponding variable name $user Will match the {user} In this way, Larvel will automatically inject the user model instance corresponding to the ID passed in the request URI.

If the corresponding model instance cannot be found in the database, an HTTP 404 response will be automatically generated.

Custom Key Name

If you want to use other fields in the data table for implicit model binding, you can override the getRouteKeyName method:

 /** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return 'slug'; }

Explicit binding

To register an explicit binding, you need to use the model Method to specify a binding class for the given parameter. belong RouteServiceProvider::boot Define model binding in method:

Bind parameters to model

 public function boot(Router $router) { parent::boot($router); $router->model('user', 'App\User'); }

Next, define a containing {user} Route of parameters:

 $router->get('profile/{user}', function(App\User $user) { // });

Because we have already bound {user} Parameters to App\User Model, the User instance will be injected into the route. Therefore, if the request URL is profile/1 A User instance with user ID 1 will be injected.

If the matched model instance does not exist in the database, an HTTP 404 response will be automatically generated and returned.

Custom parsing logic

If you want to use custom parsing logic, you need to use Route::bind Method, passing to bind The closure of the method will get the value in the URI request parameter and return the class instance you want to inject in the route:

 $router->bind('user', function($value) { return App\User::where('name', $value)->first(); });

Customize Not Found

If you want to specify your own "Not Found" behavior, pass the closure encapsulating this behavior as the third parameter to model method:

 $router->model('user', 'App\User', function() { throw new NotFoundHttpException; });

7. Form method forgery

HTML forms do not support PUT, PATCH or DELETE request methods. Therefore, when PUT, PATCH or DELETE routes, you need to add a hidden _method Field to the form, and its value is used as the HTTP request method of the form:

 <form action="/foo/bar" method="POST"> <input type="hidden" name="_method" value="PUT"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> </form>

You can also use auxiliary functions method_field To achieve this goal:

 <? php echo method_field('PUT'); ?>

Of course, it also supports the Blade template engine:

 {{ method_field('PUT') }}

give the thumbs-up Cancel Like Collection Cancel Collection

<<Previous: Task management system with user function

>>Next: HTTP middleware