Introduction
Middleware is just a layer before route handler
. This layer can make our program much more maintainable and readable. The middleware layer is an extra layer but this extra layer makes our life easy by not repeating the same code again and again.
Do you know route handler!
What is route handler?
Whenever you call any route then the corresponding method to that route is being called and that method is called as route handler. Route handler could be Method from the Controller also.
Understand with a particle example
Suppose you have a shopping website and there are lots of routes.
- Some route: Anyone can see some pages.
- Some route: Only Authenticated user can see some page.
Before ordering anything from the shopping website, you will check if the user is logged in or not. Before adding a product to the cart you will see if the user is authenticated or not.
You are checking if the user is logged in or not on every page which is built for the authenticated users.
Checking of the authentication can be done from the route handler and as well as from the middleware. If we will do the checking using a route handler or controller then your method will look something similar to this.
<?php
Route::get('/', function () {
return view('home');
});
Route::get('/login', function(){
return view('home');
});
Route::get('/register', function(){
return view('register');
});
Route::get('/order', function(){
// Check if user if authenticated
return view('order');
});
Route::get('/profile', function(){
// Check if user if authenticated
return view('profile');
});
Route::get('/wallet', function(){
// Check if user if authenticated
return view('wallet');
});
Route::get('/return_product', function(){
// Check if user if authenticated
return view('return_product');
});
We are checking if the user is authenticated or not and if not authenticated the redirect to the login page. This is being done by 5 lines of code. We are writing these 5 lines in most of the routes which are not good code because there is no code reusability. As the LOC(lines of code) increases maintainability becomes difficult.
If you will use Middleware to solve your problem then you will end up using
- Writing the authentication Chekiang code once
- Attaching the Middleware on any route with one line of code.
- If you want to make some changes to the authentication method then you have to make changes in the middleware once it will be applied to all the routes where you had applied.
Example
In this example, we will create a middleware and check the URL Params
. If the URL params are less than an 18 then we will stop the user from accessing that webpage. If the number is greater than 18 then we will show the webpage to the user.
First, if all we will register a new route and show call a view corresponding the route.
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('/vote', function(){
// Let's call the view corresponding to the vote page
return view('vote');
});
Now let’s create the view, this view will be shown whenever user will send GET request on the /vote
url.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div style="min-height:50vh;background:#101820;width:100%" class="d-flex align-items-center justify-content-center">
<h1 class="text-center text-light">
Thanks for coming to vote
</h1>
</div>
<div style="min-height:50vh;background:#F2AA4C;width:100%" class="d-flex align-items-center justify-content-center">
<h1 class="text-center text-light">
Please vote for your leader
</h1>
</div>
</body>
</html>
First let’s do without middleware
We want that whenever user sends their age less than 18 then we will strictly don’t show the vote page to them.
User will send the age using the
URL Params
with the key name age.
When the user will route to then http://localhost:8080/vote?age=16
it will redirect to some other page.
When the user will route to then http://localhost:8080/vote?age=19
it will show the vote page.
So from the above URL, you got the idea that we doing are doing this based on the age value. So, In our /vote
route handler, we will get the age and check if it is greater than 18 or not! Based on the age we will decide what to do. Once we achieve this then we will do this using middleware.
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('/vote', function(){
$age = request()->age ;
if ($age < 18) {
return redirect('/');
}else{
return view('vote');
}
});
- $request->age: This line of code will get the code from the URL.
After getting the age, we have added the logic for checking the age. If the age is less than 18 then it will redirect to /
else it will show the vote
page.
$age = $request->age ;
if ($age < 18) {
return redirect('/');
}else{
return view('vote');
}
We can do this using middleware also, but the question is why to use middleware when we can solve it using middleware. Middleware helps us to an abstraction layer, If we need to do any kind of validation in some of the routes then using middleware is the best to approach because we will write the code once and add middleware to all required routes.
Let’s see how we can do this using middleware.
Create Middleware
Let’s create a middleware using this command
.
php artisan make:middleware AgeCheck
When you create the middleware it creates the file in the location app/Hpp/Middleware/
. Our middleware name is AgeCheck and it can be found at app/Hpp/Middleware/AgeCheck
When you will open the middleware then you find code similar to this.
We will add our logic in the handler method of this Middleware.
Middleware handler
method decide weather, what to do with the request before reaching it to theroute handler
.
<?php
namespace App\Http\Middleware;
use Closure;
class AgeCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
This line of code is responsible for forwarding the request to the route handler
. We want to forward the request to route handler
in one case only and that is, when age is not less than 18.
return $next($request);
Now, We have logic remove the logic from the
route handler
and put it in theMiddleware handler
. We have this logic in theroute handler
.
$age = $request->age ;
if ($age < 18) {
return redirect('/');
}else{
return view('vote');
}
In the middleware, we will add the logic in the route and that logic will decide whether it wants to forward the request to the route handler
or not!
We have to make a change which is, Instead of return the view when age is not less than 18 we will forward the request to the route handler
and route handler
will show the view.
Handler code now looks like this
$age = $request->age ;
if ($age < 18) {
return redirect('/');
}else{
return $next($request);
}
Our Middleware will look something like this.
<?php
namespace App\Http\Middleware;
use Closure;
class AgeCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if($request->age < 18){
return redirect('/');
}else{
return $next($request);
}
}
}
Register Middleware
Now you need to attach the middleware with the route but before attaching it to the route we need to register it in the kernal.php
Kernel.php file is very big to include in this article so I am attaching part of it, which will make sense to you. You can understand this also.
I had added one
key-value pair
at the top in the associated array.
'agecheck' => \App\Http\Middleware\AgeCheck::class
This will register the Middleware and now you can use this middleware in your Laravel app.
protected $routeMiddleware = [
'agecheck' => \App\Http\Middleware\AgeCheck::class,
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
Attach Middleware to the route
Now we will attach the registered middleware tot the route and we will also remove the logic from it. Now logic is being handled by the middleware.
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('/vote', function(){
return view('vote');
})->middleware('agecheck');
You have successfully made your first middleware and now you are can apply this concept in your application also.
Apply the concept of middleware to those places where you are doing a similar kinds of things in various route
. You don’t need middleware when you are doing something in one or two routes.
To know more about the Middleware you should watch this video
Video about Laravel Middleware
Thanks for coming to my blog and reading. If you like it then please let me via tweet or comment.
Tweet #nitishk72_