January 8, 2024 · 4 min read · 26 views
Laravel middleware is like the security team for your application. They check the credentials of incoming HTTP requests and decide whether to let them through to your application, hold them for further inspection, or turn them away.
Middleware in Laravel is a type of filtering mechanism. It's a layer that sits between the request and the response. You can use middleware for a variety of tasks, such as authenticating users, logging requests, or even modifying the request before it reaches your application logic.
When a request enters your Laravel application, it goes through a stack of middleware before reaching the route that handles it. After the route's controller does its work, the response generated by the controller also goes through the middleware stack before it's sent back to the user.
To create a new middleware in Laravel, you can use the Artisan command-line tool:
php artisan make:middleware CheckAuthorStatus
This command generates a new middleware class named CheckAuthorStatus
in the app/Http/Middleware
directory.
Let's say we want to create a middleware that checks if the authenticated user is an author before allowing them to create a new blog post.
Here's what our CheckAuthorStatus
middleware might look like:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class CheckAuthorStatus
{
public function handle(Request $request, Closure $next)
{
if (Auth::check() && Auth::user()->is_author) {
return $next($request);
}
return redirect('home')->with('error', 'Only authors can create a post.');
}
}
In this middleware, we're checking if the user is authenticated and if they have an is_author
property set to true
. If they're not an author, we redirect them to the home page with an error message.
For this to work, we need to modify our user migration and add a new column that will modify the state of a user to an author. Since our app is not live yet, we can go ahead and make the change in the migration directly:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('email_verified_at')->nullable();
$table->string('password');
$table->boolean('is_author')->default(false);
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
}
We will save it as a boolean value where the default value is false.
But, if the site is live, we cannot make the change without losing previous data. We have to write a new migration script that will modify the user migration:
php artisan make:migration add_is_author_to_users_table --table=users
Next, you would update the migration file to include the new column:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIsAuthorToUsersTable extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_author')->default(false);
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_author');
});
}
}
After creating the migration, run the migration command to update the database:
php artisan migrate
Now, your users
table has an is_author
boolean column that you can use to determine if a user is an author.
After creating middleware, you need to register it in your application before it can be used. Middleware can be registered globally, assigned to routes, or grouped within route groups.
To register middleware, add it to the $routeMiddleware
array in the app/Http/Kernel.php
file:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::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,
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'check.author' => \App\Http\Middleware\CheckAuthorStatus::class,
];
}
Now, you can use the check.author
middleware in your routes.
With our CheckAuthorStatus
middleware registered, we can use it in our routes file to protect the route that creates new blog posts:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
Route::get('/posts/create', [PostController::class, 'create'])->middleware('check.author');
Now, only users who are authors can access the form to create a new blog post.
Middleware can also receive additional parameters. For example, you might want to have a middleware that checks if a user has a specific role:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class CheckUserRole
{
public function handle(Request $request, Closure $next, $role)
{
if (Auth::check() && Auth::user()->role === $role) {
return $next($request);
}
return redirect('home')->with('error', "You do not have access here.");
}
}
You can pass the $role
parameter to the middleware in your route definition like so:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
Route::get('/admin', [AdminController::class, 'index'])->middleware('role:admin');
Middleware in Laravel serves as the guardian of your application, ensuring that only valid requests are processed by your routes and controllers. They are incredibly flexible and powerful tools for managing HTTP requests and responses. By using middleware, you can add layers of protection, handle authentication, perform logging, and more, keeping your blog secure and running smoothly. As you become more familiar with Laravel middleware, you'll discover even more ways to enhance the functionality and security of your blog application.
If you need help with a Laravel project let's get in touch.
Lucky Media is proud to be recognized as a Top Laravel Development Agency
Technologies:
Related Posts
Stay up to date
Be updated with all news, products and tips we share!