Middleware Tutorial in Laravel 11

 <?php


namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class UserController extends Controller
{
    public function register(Request $request)
    {
        $data = $request->validate([
            "name" => "required",
            "email" => "required|email",
            "age" => "required",
            "password" => "required|confirmed",
            "role" => "required"
        ]);

        // if above validation form-field names and database column names both are same then only we can pass above "$data" variable as shown below :
        // Using below code, we can create data in database
        $user = User::create($data);

        // when data is created in database at that time, id will be return in above "$user" variable
        if($user) {
            return redirect()->route("login");
        }
    }

    public function login(Request $request)
    {
        $credentials = $request->validate([
            "email" => "required|email",
            "password" => "required"
        ]);

        if(Auth::attempt($credentials)) {
            return redirect()->route("dashboard");
        }
    }

    public function dashboardPage()
    {
        return view("dashboard");

        // if(Auth::check()) {
        //     return view("dashboard");
        // } else {
        //     return redirect()->route("login");
        // }
    }

    public function innerPage()
    {
        // check() and guest() method both are opposite
        // check() method checks that user is already logged in or not
        // guest() method checks that user is already not logged in or not
        // if(Auth::check()) {
        //     return view("inner");
        // } else {
        //     return redirect()->route("login");
        // }

        return view("inner");
    }

    public function logout()
    {
        Auth::logout(); //Auth:logout() will destroy session
        return view("login");
    }
}
Above File is app\Http\Controllers\UserController File





Below File is app\Http\Middleware\TestUser File
<?php

namespace App\Http\Middleware;

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

class TestUser
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        echo "<h3 class='text-success'>Test User middleware</h3>";
        return $next($request);
    }
}





Below File is app\Http\Middleware\ValidUser File
<?php

namespace App\Http\Middleware;

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

class ValidUser
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next, string $role): Response
    {
        echo "<h3 class='text-primary'>We are now in ValidUser MiddleUser.</h3>";
        echo "<h3 class='text-primary'>".$role."</h3>";


        if(Auth::user()->role == $role) {
            return $next($request);
        } else if(Auth::user()->role == "reader") {
            return redirect()->route("user");
        }
        else {
            return redirect()->route("login");
        }

        // if(Auth::check() && Auth::user()->role == $role) {
        //     return $next($request);
        // } else {
        //     return redirect()->route("login");
        // }
    }

    // Below "terminate" method will run after completing User request
    public function terminate(Request $request, Response $response): void
    {
        echo "<h3 class='text-danger'>We are now Terminating ValidUser MiddleUser.</h3>";
    }
}





Below File is app\Models\User File
<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable;
    public $timestamps = false;
    protected $table = "users";

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        "age",
        "role",
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}





Below File is bootstrap\app File
<?php

use App\Http\Middleware\ValidUser;
use App\Http\Middleware\TestUser;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->alias([
            "IsUserValid" => ValidUser::class
        ]);

        // we can also use "prependToGroup()" method instead of "appendToGroup()" method
        // $middleware->prependToGroup("ok-user",[
        //     ValidUser::class,
        //     TestUser::class
        // ]);

        // Below is Global middleware will apply all routes automatically
        $middleware->append(TestUser::class);

        // If we want to use multiple Global middleware simultaneously to all routes then we can do as shown below :
        // $middleware->use([
        // TestUser::class,
        // ValidUser::class
        // ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();






Below File is database\migrations\2024_12_24_141917_create_users_table File
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string("name");
            $table->string("email");
            $table->integer("age");
            $table->string("password");
            $table->string("role");
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};






Below File is database\migrations\2024_12_24_160251_update_users_table File
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table("users", function(Blueprint $table){
            $table->string("role")->after("age")->change();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        //
    }
};






Below File is resources\views\dashboard File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Dashboard</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-6 mt-5 mb-3">
                <h1 class="mb-5">Welcome {{ Auth::user()->name }}</h1>
                {{-- Showing User information as shown below : --}}
                {{-- {{ Auth::user() }} --}}
            </div>
        </div>
        <div class="row justify-content-center">
            <div class="col-6">
                <a href="{{ route("inner") }}" class="btn btn-primary">Go to Inner Page</a>
                <a href="{{ route("logout") }}" class="btn btn-danger">Logout</a>
            </div>
        </div>
    </div>
</body>
</html>





Below File is resources\views\inner File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>InnerPage</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-5 mt-5 mb-3">
                <h1>Inner Page</h1>
            </div>
        </div>
        <div class="row justify-content-center">
            <div class="col-5">
                <a href="{{ route("dashboard") }}" class="btn btn-primary">Back to Dashboard</a>
                <a href="{{ route("logout") }}" class="btn btn-danger">Logout</a>
            </div>
            <div class="col-5">
                @if(Auth::check())
                    {{ Auth()->user()->id }}
                    {{ Auth()->user()->name }}
                @endif
            </div>
        </div>
    </div>
</body>
</html>




Below File is resources\views\login File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Login</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-5 mt-5">
                <div class="card">
                    <div class="card-header">
                        <h3>Login</h3>
                    </div>
                    <div class="card-body">
                        <form action="{{ route("loginMatch") }}" method="POST">
                            @csrf
                            <div class="mb-3">
                                <label for="useremail" class="form-label">Email Address</label>
                                <input type="email" value="{{ old("email") }}" name="email" class="form-control @error("email") is-invalid @enderror" id="useremail">
                                <span class="text-danger">
                                    @error("email")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <div class="mb-3">
                                <label for="userpassword" class="form-label">Password</label>
                                <input type="password" value="{{ old("password") }}" name="password" class="form-control @error("password") is-invalid @enderror" id="userpassword">
                                <span class="text-danger">
                                    @error("password")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <button type="submit" class="btn btn-primary">Login</button>
                            <a href="{{ route("welcomeTwo") }}" class="btn btn-secondary">Back</a>
                        </form>
                    </div>
                    @if($errors->any())
                        <div class="card-footer text-body-secondary">
                            <div class="alert alert-danger">
                                <ul>
                                    @foreach($errors->all() as $error)
                                        <li>{{ $error }}</li>
                                    @endforeach
                                </ul>
                            </div>
                        </div>
                    @endif
                </div>
            </div>
        </div>
    </div>
</body>
</html>





Below File is resources\views\register File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Register</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-5 mt-5">
                <div class="card">
                    <div class="card-header">
                        <h3>Register</h3>
                    </div>
                    <div class="card-body">
                        <form action="{{ route("registerSave") }}" method="POST">
                            @csrf
                            <div class="mb-3">
                                <label for="username" class="form-label">Name</label>
                                <input type="text" value="{{ old("name") }}" name="name" class="form-control @error("name") is-invalid @enderror" id="username">
                                <span class="text-danger">
                                    @error("name")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <div class="mb-3">
                                <label for="useremail" class="form-label">Email Address</label>
                                <input type="email" value="{{ old("email") }}" name="email" class="form-control @error("email") is-invalid @enderror" id="useremail"/>
                                <span class="text-danger">
                                    @error("email")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <div class="mb-3">
                                <label for="userage" class="form-label">Age</label>
                                <input type="text" value="{{ old("age") }}" name="age" class="form-control @error("age") is-invalid @enderror" id="userage"/>
                                <span class="text-danger">
                                    @error("age")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <div class="mb-3">
                                <label for="userpassword" class="form-label">Password</label>
                                <input type="password" value="{{ old("password") }}" name="password" class="form-control @error("password") is-invalid @enderror" id="userpassword">
                                <span class="text-danger">
                                    @error("password")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <div class="mb-3">
                                <label for="userpassword-confirm" class="form-label">Confirm Password</label>
                                {{-- it is necessary to take name="password_confirmation" as in proper format then only it will validate using laravel's "confirm" validation rule --}}
                                <input type="password" value="{{ old("password_confirmation") }}" name="password_confirmation" class="form-control @error("password_confirmation") is-invalid @enderror" id="userpassword-confirm">
                                <span class="text-danger">
                                    @error("password_confirmation")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <div class="mb-3">
                                <label for="userrole" class="form-label">Role</label>
                                <input type="text" value="{{ old("role") }}" name="role" class="form-control @error("role") is-invalid @enderror" id="userrole"/>
                                <span class="text-danger">
                                    @error("role")
                                        {{ $message }}
                                    @enderror
                                </span>
                            </div>
                            <button type="submit" class="btn btn-primary">Register</button>
                            <a href="/" class="btn btn-secondary">Back</a>
                        </form>
                    </div>

                    @if($errors->any())
                        <div class="card-footer text-body-secondary">
                            <div class="alert alert-danger">
                                <ul>
                                    @foreach($errors->all() as $error)
                                        <li>{{ $error }}</li>
                                    @endforeach
                                </ul>
                            </div>
                        </div>
                    @endif
                </div>
            </div>
        </div>
    </div>
</body>
</html>





Below File is resources\views\user File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Reader</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-5 mt-5">
                <div class="card">
                    <div class="card-header">
                        <h3>Reader Page</h3>
                    </div>
                    <div class="card-body">
                        Hello, Reader
                        <a href="{{ route("logout") }}" class="btn btn-danger">Logout</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>





Below File is resources\views\welcomeTwo File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Welcome</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-5 mt-5 mb-3">
                <h1>Laravel Authentication</h1>
            </div>
        </div>
        <div class="row justify-content-center">
            <div class="col-5">
                <a href="{{ route("register") }}" class="btn btn-primary">Register</a>
                <a href="{{ route("login") }}" class="btn btn-primary">Login</a>
            </div>
        </div>
    </div>
</body>
</html>





Below File is routes\web File
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Middleware\ValidUser;
use App\Http\Middleware\TestUser;

Route::get('/', function () {
    return view('welcome');
});

Route::get("/user", function(){
    return view("user");
})->name("user");

Route::view("welcomeTwo","welcomeTwo")->name("welcomeTwo");

Route::view("register","register")->name("register");

Route::view("login","login")->name("login");

Route::controller(UserController::class)->group(function(){
    Route::post("registerSave","register")->name("registerSave");
    Route::post("loginMatch","login")->name("loginMatch");

    // sending role "admin" along with middleware as shown below :
    // Route::get("dashboard","dashboardPage")->name("dashboard")->middleware(["IsUserValid:admin",TestUser::class]);
    // Route::get("dashboard/inner","innerPage")->name("inner")->middleware(["IsUserValid:admin",TestUser::class]);


    // Laravel provides in-built own middleware as shown below :
    // Route::get("dashboard","dashboardPage")->name("dashboard")->middleware(["auth","IsUserValid:admin"]);
    // Route::get("dashboard/inner","innerPage")->name("inner")->middleware(["auth","IsUserValid:admin"]);


    // Applying Global middleware as show below :
    Route::get("dashboard","dashboardPage")->name("dashboard");
    Route::get("dashboard/inner","innerPage")->name("inner");


    // Below is route middleware Technique
    // Below is for apply multiple middleware simultaneously
    // we can apply above both middleware by making below group of middleware as shown below :
    // Route::middleware(["IsUserValid",TestUser::class])->group(function(){
    //     Route::get("dashboard","dashboardPage")->name("dashboard");
    //     // if we want to not apply any particular middleware to any particular route then we can do as shown below :
    //     Route::get("dashboard/inner","innerPage")->name("inner")->withoutMiddleware([TestUser::class]);
    // });

    // Below is route middleware Technique
    // Below is for apply multiple withoutMiddleware simultaneously
    // we can apply withoutMiddleware group to apply multiple middleware as shown below :
    // Route::withoutMiddleware([TestUser::class])->group(function(){
    //     Route::get("dashboard/inner","innerPage")->name("inner");
    // });



    // Below is "Group-middleware" Technique
    // Route::middleware(["ok-user"])->group(function(){
    //     Route::get("dashboard","dashboardPage")->name("dashboard");
    //     // if we want to not apply any particular middleware to any particular route then we can do as shown below :
    //     Route::get("dashboard/inner","innerPage")->name("inner")->withoutMiddleware([TestUser::class]);
    // });

    Route::get("logout","logout")->name("logout");
});












Comments

Popular posts from this blog

Eloquent Many to Many Relationship Tutorial in Laravel 11

Blade Template Tutorial Three Template Inheritance in Laravel 11