Laravel Development

Understanding Laravel Middleware: The Complete Guide

Master Laravel 12 middleware with this comprehensive guide covering creation, registration, authentication, security, performance optimization, and real-world examples for building secure PHP applications.

Muhammad Waqas

Muhammad Waqas

CEO at CentoSquare

|
03-Nov-2025
3 min read
Understanding Laravel Middleware: The Complete Guide

Laravel middleware is one of the most powerful features in the framework, acting as a bridge between incoming HTTP requests and your application's core logic. Whether you're building a simple blog or a complex enterprise application, understanding middleware is essential for creating secure, maintainable, and efficient Laravel applications.

In this comprehensive guide, we'll explore everything you need to know about Laravel 12 middleware, from basic concepts to advanced implementations and best practices.

What is Middleware in Laravel?

Middleware provides a convenient mechanism for inspecting and filtering HTTP requests entering your application. Think of middleware as a series of layers or checkpoints that HTTP requests must pass through before reaching your application's core functionality.

For example, Laravel includes built-in middleware that verifies whether a user is authenticated. If the user isn't authenticated, the middleware redirects them to the login screen. However, if the user is authenticated, the middleware allows the request to proceed deeper into the application.

Middleware can be used for various purposes beyond authentication:

  • Request logging: Track all incoming requests for debugging and analytics
  • CSRF protection: Ensure requests are legitimate and secure
  • Data validation: Validate incoming data before it reaches controllers
  • Rate limiting: Prevent abuse by limiting request frequency
  • CORS handling: Manage cross-origin resource sharing policies
  • API token verification: Authenticate API requests
  • Role-based access control: Restrict access based on user roles
  • Request/response modification: Transform data before processing or sending

How Middleware Works: The Request Lifecycle

Understanding how middleware fits into Laravel's request lifecycle is crucial. When an HTTP request enters your Laravel application, it follows this path:

  1. The request enters through the public/index.php file
  2. Laravel bootstraps the application and loads the service providers
  3. The request passes through the global middleware stack
  4. Laravel's router matches the request to a route
  5. Route-specific middleware executes
  6. The request reaches your controller or route handler
  7. The response travels back through the middleware layers
  8. Finally, the response is sent to the client

This pipeline architecture allows each middleware layer to examine, modify, or even reject requests entirely before they reach your application logic.

Creating Custom Middleware in Laravel 12

Creating middleware in Laravel 12 is straightforward using the Artisan command-line tool. Let's walk through the process of creating a custom middleware.

Step 1: Generate Middleware

Use the make:middleware Artisan command to create a new middleware class:

php artisan make:middleware EnsureTokenIsValid

This command creates a new file in the app/Http/Middleware directory with the basic middleware structure already in place.

Step 2: Implement Middleware Logic

Open the generated EnsureTokenIsValid.php file. You'll see a basic template with a handle method:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureTokenIsValid
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->input('token') !== 'my-secret-token') {
            return redirect('/home')->with('error', 'Invalid token provided');
        }

        return $next($request);
    }
}

The handle method receives two parameters:

  • $request: The incoming HTTP request object
  • $next: A closure that represents the next middleware in the stack

To allow the request to proceed, call $next($request). To reject the request, return a response or redirect.

Step 3: Before and After Middleware

Middleware can perform tasks before or after the request is handled by the application.

Before Middleware (executed before the request reaches the controller):

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class BeforeMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        // Perform action before the request is handled
        Log::info('Request received: ' . $request->path());
        
        return $next($request);
    }
}

After Middleware (executed after the request is handled):

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class AfterMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);
        
        // Perform action after the request is handled
        Log::info('Response sent: ' . $response->getStatusCode());
        
        return $response;
    }
}

Registering Middleware in Laravel 12

One of the significant changes in Laravel 12 is how middleware is registered. Instead of the traditional app/Http/Kernel.php file, middleware registration now occurs in the bootstrap/app.php file. This change centralizes configuration and makes the setup process more intuitive.

The New Bootstrap/App.php Structure

Here's the basic structure of bootstrap/app.php in Laravel 12:

<?php

use Illuminate\Foundation\Application;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function ($middleware) {
        // Register middleware here
    })
    ->withExceptions(function ($exceptions) {
        //
    })
    ->create();

Global Middleware

Global middleware runs on every HTTP request to your application. To register global middleware, use the append or prepend methods within the withMiddleware closure:

->withMiddleware(function ($middleware) {
    $middleware->append(\App\Http\Middleware\EnsureTokenIsValid::class);
})

Use append to add middleware to the end of the global stack, or prepend to add it to the beginning:

->withMiddleware(function ($middleware) {
    $middleware->prepend(\App\Http\Middleware\LogRequests::class);
    $middleware->append(\App\Http\Middleware\CompressResponse::class);
})

Route Middleware

Route middleware is assigned to specific routes or route groups. To register route middleware (also called middleware aliases), use the alias method:

->withMiddleware(function ($middleware) {
    $middleware->alias([
        'admin' => \App\Http\Middleware\CheckAdmin::class,
        'verified.email' => \App\Http\Middleware\EnsureEmailIsVerified::class,
        'check.token' => \App\Http\Middleware\EnsureTokenIsValid::class,
    ]);
})

Middleware Groups

Middleware groups allow you to bundle multiple middleware under a single key, making it easier to apply them to routes:

->withMiddleware(function ($middleware) {
    $middleware->appendToGroup('api', [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    ]);
})

Laravel 12 comes with pre-configured middleware groups like web and api. You can add your custom middleware to these groups or create new groups entirely.

Applying Middleware to Routes

Once middleware is registered, you can apply it to routes in several ways.

Single Route Middleware

Apply middleware to individual routes using the middleware method:

use Illuminate\Support\Facades\Route;

Route::get('/dashboard', function () {
    // Dashboard logic
})->middleware('auth');

Multiple Middleware on a Route

Chain multiple middleware by passing an array:

Route::get('/admin/settings', function () {
    // Admin settings
})->middleware(['auth', 'admin', 'verified.email']);

Route Group Middleware

Apply middleware to a group of routes:

Route::middleware(['auth', 'verified.email'])->group(function () {
    Route::get('/profile', [ProfileController::class, 'show']);
    Route::put('/profile', [ProfileController::class, 'update']);
    Route::delete('/profile', [ProfileController::class, 'destroy']);
});

Controller Middleware

Apply middleware directly in your controller's constructor:

<?php

namespace App\Http\Controllers;

class AdminController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('admin')->only(['destroy', 'create']);
        $this->middleware('log.request')->except(['index']);
    }
}

Middleware Parameters

Middleware can accept additional parameters, making them more flexible and reusable. This is particularly useful for role-based access control or feature flags.

Creating Parameterized Middleware

Here's an example of middleware that checks user roles:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckRole
{
    public function handle(Request $request, Closure $next, string $role): Response
    {
        if (! $request->user() || ! $request->user()->hasRole($role)) {
            abort(403, 'Unauthorized action.');
        }

        return $next($request);
    }
}

Using Parameterized Middleware

Pass parameters to middleware using a colon separator:

Route::get('/admin/dashboard', function () {
    // Admin only
})->middleware('role:admin');

Route::get('/moderator/panel', function () {
    // Moderator only
})->middleware('role:moderator');

You can pass multiple parameters separated by commas:

Route::get('/content/edit', function () {
    // Edit content
})->middleware('role:admin,editor');

Your middleware would receive these as separate parameters:

public function handle(Request $request, Closure $next, string ...$roles): Response
{
    if (! $request->user() || ! $request->user()->hasAnyRole($roles)) {
        abort(403, 'Unauthorized action.');
    }

    return $next($request);
}

Dependency Injection in Middleware

Laravel's service container resolves all middleware, allowing you to type-hint any dependencies you need in the middleware constructor:

<?php

namespace App\Http\Middleware;

use App\Services\TokenService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ValidateApiToken
{
    protected $tokenService;

    public function __construct(TokenService $tokenService)
    {
        $this->tokenService = $tokenService;
    }

    public function handle(Request $request, Closure $next): Response
    {
        $token = $request->header('X-API-Token');
        
        if (! $this->tokenService->isValid($token)) {
            return response()->json(['error' => 'Invalid API token'], 401);
        }

        return $next($request);
    }
}

Terminable Middleware

Sometimes you need to perform work after the HTTP response has been sent to the browser. Terminable middleware allows you to do this by implementing a terminate method:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class TerminableMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        return $next($request);
    }

    public function terminate(Request $request, Response $response): void
    {
        // Perform tasks after response is sent
        // This won't delay the response to the user
        Log::info('Response completed', [
            'status' => $response->getStatusCode(),
            'path' => $request->path(),
        ]);
    }
}

The terminate method is called after the response has been sent to the user, making it ideal for tasks like logging, data syncing, or cleanup operations that don't need to block the response.

Real-World Middleware Examples

Let's explore some practical middleware implementations you might use in production applications.

API Rate Limiting Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;

class RateLimitApi
{
    public function handle(Request $request, Closure $next, int $maxAttempts = 60): Response
    {
        $key = 'rate-limit:' . $request->ip();
        $attempts = Cache::get($key, 0);

        if ($attempts >= $maxAttempts) {
            return response()->json([
                'error' => 'Too many requests. Please try again later.'
            ], 429);
        }

        Cache::put($key, $attempts + 1, now()->addMinute());

        $response = $next($request);
        
        $response->headers->set('X-RateLimit-Limit', $maxAttempts);
        $response->headers->set('X-RateLimit-Remaining', $maxAttempts - $attempts - 1);

        return $response;
    }
}

Request Logging Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;

class LogRequests
{
    public function handle(Request $request, Closure $next): Response
    {
        $startTime = microtime(true);
        
        $response = $next($request);
        
        $duration = microtime(true) - $startTime;
        
        Log::info('HTTP Request', [
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'ip' => $request->ip(),
            'user_id' => $request->user()?->id,
            'status' => $response->getStatusCode(),
            'duration' => round($duration * 1000, 2) . 'ms',
        ]);

        return $response;
    }
}

Force HTTPS Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ForceHttps
{
    public function handle(Request $request, Closure $next): Response
    {
        if (! $request->secure() && app()->environment('production')) {
            return redirect()->secure($request->getRequestUri(), 301);
        }

        return $next($request);
    }
}

Sanitize Input Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class SanitizeInput
{
    public function handle(Request $request, Closure $next): Response
    {
        $input = $request->all();
        
        array_walk_recursive($input, function (&$value) {
            if (is_string($value)) {
                $value = strip_tags($value);
                $value = trim($value);
            }
        });
        
        $request->merge($input);

        return $next($request);
    }
}

Localization Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Symfony\Component\HttpFoundation\Response;

class SetLocale
{
    public function handle(Request $request, Closure $next): Response
    {
        $locale = $request->segment(1);
        $availableLocales = ['en', 'es', 'fr', 'de'];
        
        if (in_array($locale, $availableLocales)) {
            App::setLocale($locale);
        }

        return $next($request);
    }
}

Built-in Laravel Middleware

Laravel 12 includes several powerful built-in middleware classes that handle common tasks:

Authentication Middleware

  • Authenticate: Ensures the user is logged in
  • RedirectIfAuthenticated: Redirects authenticated users away from guest-only pages

CSRF Protection

  • VerifyCsrfToken: Protects against cross-site request forgery attacks on POST, PUT, PATCH, and DELETE requests

Session Management

  • StartSession: Handles session data
  • ShareErrorsFromSession: Makes validation errors available in views

Cookie Encryption

  • EncryptCookies: Automatically encrypts and decrypts cookies
  • AddQueuedCookiesToResponse: Adds cookies to the response

Security Headers

  • HandleCors: Manages Cross-Origin Resource Sharing (CORS) policies
  • TrustProxies: Configures trusted proxies for applications behind load balancers

Maintenance Mode

  • PreventRequestsDuringMaintenance: Blocks requests when the application is in maintenance mode

Middleware Best Practices

Following these best practices will help you create maintainable, secure, and performant middleware:

Keep Middleware Simple and Focused

Each middleware should have a single responsibility. If your middleware is doing too much, consider splitting it into multiple middleware classes:

// Bad: Middleware doing too many things
class HandleRequestMiddleware
{
    public function handle($request, $next)
    {
        // Authenticate
        // Validate
        // Log
        // Transform data
        // etc...
    }
}

// Good: Separate concerns
class AuthenticateMiddleware { }
class ValidateRequestMiddleware { }
class LogRequestMiddleware { }
class TransformRequestMiddleware { }

Use Middleware Parameters for Flexibility

Make middleware reusable by accepting parameters:

// Instead of creating CheckAdminMiddleware, CheckModeratorMiddleware, etc.
// Create one flexible middleware
class CheckRole
{
    public function handle($request, $next, ...$roles)
    {
        if (! $request->user()->hasAnyRole($roles)) {
            abort(403);
        }
        return $next($request);
    }
}

// Usage
Route::get('/admin', fn() => '...')->middleware('role:admin');
Route::get('/content', fn() => '...')->middleware('role:admin,editor');

Order Middleware Appropriately

The order of middleware execution matters. Place authentication middleware before middleware that requires user data:

Route::middleware(['auth', 'verified', 'role:admin'])->group(function () {
    // Routes here
});

Avoid Middleware Overuse

Not every piece of logic belongs in middleware. Use middleware for cross-cutting concerns that apply to multiple routes. For route-specific logic, consider using:

  • Controller methods
  • Form request validation classes
  • Service classes
  • Route model binding

Optimize Middleware Performance

Keep middleware logic lightweight. For expensive operations, consider:

  • Using caching to avoid repeated calculations
  • Moving heavy processing to queued jobs
  • Implementing terminable middleware for post-response tasks
public function handle($request, $next)
{
    // Fast checks only
    if (Cache::has('user-banned:' . $request->user()->id)) {
        abort(403);
    }
    
    return $next($request);
}

public function terminate($request, $response)
{
    // Heavy processing after response
    SomeHeavyJob::dispatch($request->user());
}

Handle Exceptions Gracefully

Always handle potential exceptions in middleware to prevent application crashes:

public function handle($request, $next)
{
    try {
        // Validate token
        $token = $request->header('X-API-Token');
        $this->tokenService->validate($token);
    } catch (InvalidTokenException $e) {
        return response()->json(['error' => 'Invalid token'], 401);
    }
    
    return $next($request);
}

Test Your Middleware

Write comprehensive tests for your middleware to ensure they work as expected:

<?php

namespace Tests\Feature;

use Tests\TestCase;

class CheckAdminMiddlewareTest extends TestCase
{
    public function test_non_admin_cannot_access_admin_routes()
    {
        $user = User::factory()->create(['role' => 'user']);
        
        $response = $this->actingAs($user)->get('/admin/dashboard');
        
        $response->assertStatus(403);
    }
    
    public function test_admin_can_access_admin_routes()
    {
        $admin = User::factory()->create(['role' => 'admin']);
        
        $response = $this->actingAs($admin)->get('/admin/dashboard');
        
        $response->assertStatus(200);
    }
}

Use Type Hints and Return Types

Leverage PHP's type system for better code quality and IDE support:

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

public function handle(Request $request, Closure $next): Response
{
    // Implementation
}

Document Middleware Parameters

When middleware accepts parameters, document them clearly:

/**
 * Check if the user has the required role.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @param  string  ...$roles  Required roles (admin, editor, moderator)
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function handle(Request $request, Closure $next, string ...$roles): Response
{
    // Implementation
}

Security Considerations

Middleware plays a crucial role in application security. Follow these guidelines:

Always Use CSRF Protection

Laravel's VerifyCsrfToken middleware should be included in your web middleware group for all state-changing requests:

->withMiddleware(function ($middleware) {
    $middleware->appendToGroup('web', [
        \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class,
    ]);
})

Validate API Tokens Properly

For API routes, implement proper token validation:

public function handle($request, $next)
{
    $token = $request->bearerToken();
    
    if (! $token || ! $this->isValidToken($token)) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    
    return $next($request);
}

Implement Rate Limiting

Protect your application from abuse by implementing rate limiting, especially for API endpoints and authentication routes:

Route::middleware(['throttle:60,1'])->group(function () {
    // Limited to 60 requests per minute
});

Sanitize User Input

While Laravel provides CSRF protection and SQL injection prevention, additional input sanitization in middleware can add an extra security layer:

public function handle($request, $next)
{
    $input = $request->all();
    
    array_walk_recursive($input, function (&$value) {
        if (is_string($value)) {
            $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
        }
    });
    
    $request->merge($input);
    
    return $next($request);
}

Protect Sensitive Routes

Use middleware to ensure sensitive routes are properly protected:

Route::middleware(['auth', 'verified', '2fa', 'role:admin'])->group(function () {
    // Highly sensitive admin routes
});

Debugging Middleware

When middleware doesn't work as expected, use these debugging techniques:

Enable Query Logging

public function handle($request, $next)
{
    DB::enableQueryLog();
    
    $response = $next($request);
    
    Log::debug('Queries executed:', DB::getQueryLog());
    
    return $response;
}

Log Middleware Execution

public function handle($request, $next)
{
    Log::debug('Middleware executed: ' . static::class);
    
    return $next($request);
}

Use Laravel Telescope

Laravel Telescope provides excellent insights into middleware execution, request handling, and performance metrics. Install it for development:

composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

Middleware vs. Other Laravel Features

Understanding when to use middleware versus other Laravel features is important:

Middleware vs. Form Requests

  • Use Middleware: For cross-cutting concerns that apply to multiple routes
  • Use Form Requests: For route-specific validation logic

Middleware vs. Gates and Policies

  • Use Middleware: For route-level authorization
  • Use Gates/Policies: For resource-level authorization within controllers

Middleware vs. Service Classes

  • Use Middleware: For HTTP request/response manipulation
  • Use Service Classes: For business logic that isn't tied to HTTP

Middleware vs. Events and Listeners

  • Use Middleware: For synchronous request/response handling
  • Use Events/Listeners: For decoupled, potentially asynchronous operations

Performance Optimization

Optimize middleware performance with these strategies:

Cache Expensive Operations

public function handle($request, $next)
{
    $userId = $request->user()->id;
    $permissions = Cache::remember(
        "user-permissions:{$userId}",
        3600,
        fn() => $this->permissionService->getUserPermissions($userId)
    );
    
    $request->merge(['permissions' => $permissions]);
    
    return $next($request);
}

Use Early Returns

Exit middleware as early as possible when conditions aren't met:

public function handle($request, $next)
{
    if (! $request->user()) {
        return redirect('/login');
    }
    
    if (! $request->user()->isActive()) {
        return response('Account suspended', 403);
    }
    
    return $next($request);
}

Lazy Load Dependencies

Use dependency injection wisely and avoid loading unnecessary services:

public function handle($request, $next)
{
    // Only load service if needed
    if ($request->has('validate')) {
        app(ValidationService::class)->validate($request);
    }
    
    return $next($request);
}

Common Middleware Pitfalls to Avoid

Avoid these common mistakes when working with middleware:

Not Returning the Response

Always return the result of $next($request):

// Wrong
public function handle($request, $next)
{
    if (! $request->user()) {
        redirect('/login'); // Missing return!
    }
    $next($request); // Missing return!
}

// Correct
public function handle($request, $next)
{
    if (! $request->user()) {
        return redirect('/login');
    }
    return $next($request);
}

Modifying Request After Calling $next

Modifications to the request after calling $next() won't affect the application:

// Wrong
public function handle($request, $next)
{
    $response = $next($request);
    $request->merge(['foo' => 'bar']); // Too late!
    return $response;
}

// Correct
public function handle($request, $next)
{
    $request->merge(['foo' => 'bar']);
    return $next($request);
}

Forgetting to Register Middleware

Always register your middleware in bootstrap/app.php before using it in routes.

Incorrect Middleware Order

Pay attention to middleware order. Authentication should come before authorization:

// Wrong order
Route::middleware(['role:admin', 'auth'])

// Correct order
Route::middleware(['auth', 'role:admin'])

Migrating from Laravel 11 to Laravel 12 Middleware

If you're upgrading from Laravel 11, here's how to migrate your middleware configuration:

Old Way (Laravel 11 - app/Http/Kernel.php)

protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
];

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
    ],
];

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
];

New Way (Laravel 12 - bootstrap/app.php)

->withMiddleware(function ($middleware) {
    // Global middleware
    $middleware->append(\App\Http\Middleware\TrustProxies::class);
    
    // Middleware groups
    $middleware->appendToGroup('web', [
        \App\Http\Middleware\EncryptCookies::class,
    ]);
    
    // Route middleware aliases
    $middleware->alias([
        'auth' => \App\Http\Middleware\Authenticate::class,
    ]);
})

Conclusion

Laravel middleware is a powerful feature that provides clean, reusable solutions for handling cross-cutting concerns in your application. By understanding how middleware works and following best practices, you can build more secure, maintainable, and performant Laravel applications.

Key takeaways:

  • Middleware acts as a filter for HTTP requests entering your application
  • Laravel 12 moved middleware registration from Kernel.php to bootstrap/app.php
  • Different types of middleware serve different purposes: global, route, and group middleware
  • Middleware can accept parameters for increased flexibility
  • Keep middleware simple, focused, and well-tested
  • Use middleware for security, logging, request transformation, and cross-cutting concerns
  • Follow best practices for performance, security, and maintainability

As you continue working with Laravel, you'll discover more use cases for middleware and develop your own patterns for implementing them effectively. The key is to keep your middleware focused, well-organized, and properly documented.

Happy coding!


Article Tags

Laravel Middleware Laravel 12 Laravel Tutorial PHP Framework Laravel Security Web Development Laravel Authentication Custom Middleware Laravel Best Practices Backend Development HTTP Middleware Laravel Routes Laravel Guide Request Filtering Laravel Performance

About the Author

Muhammad Waqas

Muhammad Waqas

CEO at CentoSquare

Founder & CEO at CentoSquare | Creator of NeedLaravelSite | Helping Businesses Grow with Cutting-Edge Web, Mobile & Marketing Solutions | Building Innovative Products