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

Eloquent with JSON Data Columns Tutorial in Laravel 11

Blade Template Tutorial Three Template Inheritance in Laravel 11