In this post, I'll show you how you can make laravel custom forget password and reset password. This article will show you a step-by-step example of how to do it.
Laravel has its own "forget password" function, but if you want to make your own, I'll show you how to create a "custom reset password" function in Laravel. So, you can also use different models to make custom forget passwords.
With Laravel, it's easy to make a custom forget password.
I posted an article about Laravel Custom Login and Registration. From there, I will start putting together a custom reset password function. So let's do the steps below.
Step 1: Create a Laravel Application
First, we need to get a new Laravel app using the commands below. To run the below command, open your terminal or command prompt and run the commands:
composer create-project --prefer-dist laravel/laravel demo-application |
Step 2: Create "password_resets" table
The laravel already has a "password_resets" migration for the table. But if it hasn't been made yet, you can make a new migration using the code below:
Run the below command in your terminal.
php artisan make:migration create_password_resets_table |
Place the below code in the migration file
database/migration/2014_10_12_100000_create_password_resets_table
<?php
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('password_resets', function (Blueprint $table) { $table->string('email')->index(); $table->string('token'); $table->timestamp('created_at')->nullable(); }); }
/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('password_resets'); } }; |
Step 3: Create Route.
Creating a custom route for the forget and reset link is the task at hand for this stage. Afterwards, open the routes/web.php file and add the following route.
routes/web.php
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\Auth\ForgotPasswordController; /* |-------------------------------------------------------------------------- | 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('forget-password', [ForgotPasswordController::class, 'showForgetPasswordForm'])->name('forget.password.get'); Route::post('forget-password', [ForgotPasswordController::class, 'submitForgetPasswordForm'])->name('forget.password.post'); Route::get('reset-password/{token}', [ForgotPasswordController::class, 'showResetPasswordForm'])->name('reset.password.get'); Route::post('reset-password', [ForgotPasswordController::class, 'submitResetPasswordForm'])->name('reset.password.post'); |
Step 4: Make Controller.
At this point, we need to make a new ForgotPasswordController class and insert the following code into its corresponding file:
app/Http/Controllers/Auth/ForgotPasswordController.php
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use DB; use Carbon\Carbon; use App\Models\User; use Mail; use Hash; use Illuminate\Support\Str; class ForgotPasswordController extends Controller { /** * Write code on Method * * @return response() */ public function showForgetPasswordForm() { return view('auth.forgetPassword'); } /** * Write code on Method * * @return response() */ public function submitForgetPasswordForm(Request $request) { $request->validate([ 'email' => 'required|email|exists:users', ]); $token = Str::random(64); DB::table('password_resets')->insert([ 'email' => $request->email, 'token' => $token, 'created_at' => Carbon::now() ]); Mail::send('email.forgetPassword', ['token' => $token], function($message) use($request){ $message->to($request->email); $message->subject('Reset Password'); }); return back()->with('message', 'We have e-mailed your password reset link!'); } /** * Write code on Method * * @return response() */ public function showResetPasswordForm($token) { return view('auth.forgetPasswordLink', ['token' => $token]); } /** * Write code on Method * * @return response() */ public function submitResetPasswordForm(Request $request) { $request->validate([ 'email' => 'required|email|exists:users', 'password' => 'required|string|min:6|confirmed', 'password_confirmation' => 'required' ]); $updatePassword = DB::table('password_resets') ->where([ 'email' => $request->email, 'token' => $request->token ]) ->first(); if(!$updatePassword){ return back()->withInput()->with('error', 'Invalid token!'); } $user = User::where('email', $request->email) ->update(['password' => Hash::make($request->password)]); DB::table('password_resets')->where(['email'=> $request->email])->delete(); return redirect('/login')->with('message', 'Your password has been changed!'); } } |
Step 5: Configure Email.
In this step, we'll set up email in the env file since we'll be sending an email to the reset password link from the controller:
.env
MAIL_DRIVER=smtp MAIL_HOST=smtp-mail.gmail.com MAIL_PORT=587 MAIL_USERNAME=example@gmail.com MAIL_PASSWORD=password MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=example@gmail.com |
Step 6: Create Blade Files.
At this point, we need to build blade files for the layout, login, registration pages, and home page. Hence, let's construct the files one by one:
resources/views/layout.blade.php
<!DOCTYPE html> <html> <head> <title>Laravel - ItSolutionStuff.com</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> <style type="text/css"> @import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600); body{ margin: 0; font-size: .9rem; font-weight: 400; line-height: 1.6; color: #212529; text-align: left; background-color: #f5f8fa; } .navbar-laravel { box-shadow: 0 2px 4px rgba(0,0,0,.04); } .navbar-brand , .nav-link, .my-form, .login-form { font-family: Raleway, sans-serif; } .my-form { padding-top: 1.5rem; padding-bottom: 1.5rem; } .my-form .row { margin-left: 0; margin-right: 0; } .login-form { padding-top: 1.5rem; padding-bottom: 1.5rem; } .login-form .row { margin-left: 0; margin-right: 0; } </style> </head> <body> <nav class="navbar navbar-expand-lg navbar-light navbar-laravel"> <div class="container"> <a class="navbar-brand" href="#">Laravel</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav ml-auto"> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('login') }}">Login</a> </li> <li class="nav-item"> <a class="nav-link" href="{{ route('register') }}">Register</a> </li> @else <li class="nav-item"> <a class="nav-link" href="{{ route('logout') }}">Logout</a> </li> @endguest </ul> </div> </div> </nav> @yield('content') </body> </html> |
resources/views/auth/forgetPassword.blade.php
@extends('layout') @section('content') <main class="login-form"> <div class="cotainer"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Reset Password</div> <div class="card-body"> @if (Session::has('message')) <div class="alert alert-success" role="alert"> {{ Session::get('message') }} </div> @endif <form action="{{ route('forget.password.post') }}" method="POST"> @csrf <div class="form-group row"> <label for="email_address" class="col-md-4 col-form-label text-md-right">E-Mail Address</label> <div class="col-md-6"> <input type="text" id="email_address" class="form-control" name="email" required autofocus> @if ($errors->has('email')) <span class="text-danger">{{ $errors->first('email') }}</span> @endif </div> </div> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> Send Password Reset Link </button> </div> </form> </div> </div> </div> </div> </div> </main> @endsection |
resources/views/auth/forgetPasswordLink.blade.php
@extends('layout') @section('content') <main class="login-form"> <div class="cotainer"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Reset Password</div> <div class="card-body"> <form action="{{ route('reset.password.post') }}" method="POST"> @csrf <input type="hidden" name="token" value="{{ $token }}"> <div class="form-group row"> <label for="email_address" class="col-md-4 col-form-label text-md-right">E-Mail Address</label> <div class="col-md-6"> <input type="text" id="email_address" class="form-control" name="email" required autofocus> @if ($errors->has('email')) <span class="text-danger">{{ $errors->first('email') }}</span> @endif </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">Password</label> <div class="col-md-6"> <input type="password" id="password" class="form-control" name="password" required autofocus> @if ($errors->has('password')) <span class="text-danger">{{ $errors->first('password') }}</span> @endif </div> </div> <div class="form-group row"> <label for="password-confirm" class="col-md-4 col-form-label text-md-right">Confirm Password</label> <div class="col-md-6"> <input type="password" id="password-confirm" class="form-control" name="password_confirmation" required autofocus> @if ($errors->has('password_confirmation')) <span class="text-danger">{{ $errors->first('password_confirmation') }}</span> @endif </div> </div> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> Reset Password </button> </div> </form> </div> </div> </div> </div> </div> </main> @endsection |
resources/views/email/forgetPassword.blade.php
<h1>Forget Password Email</h1> You can reset password from below link: <a href="{{ route('reset.password.get', $token) }}">Reset Password</a> |
resources/views/auth/login.blade.php
@extends('layout') @section('content') <main class="login-form"> <div class="cotainer"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Login</div> <div class="card-body"> <form action="{{ route('login.post') }}" method="POST"> @csrf <div class="form-group row"> <label for="email_address" class="col-md-4 col-form-label text-md-right">E-Mail Address</label> <div class="col-md-6"> <input type="text" id="email_address" class="form-control" name="email" required autofocus> @if ($errors->has('email')) <span class="text-danger">{{ $errors->first('email') }}</span> @endif </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">Password</label> <div class="col-md-6"> <input type="password" id="password" class="form-control" name="password" required> @if ($errors->has('password')) <span class="text-danger">{{ $errors->first('password') }}</span> @endif </div> </div> <div class="form-group row"> <div class="col-md-6 offset-md-4"> <div class="checkbox"> <label> <input type="checkbox" name="remember"> Remember Me </label> </div> </div> </div> <div class="form-group row"> <div class="col-md-6 offset-md-4"> <div class="checkbox"> <label> <a href="{{ route('forget.password.get') }}">Reset Password</a> </label> </div> </div> </div> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> Login </button> </div> </form> </div> </div> </div> </div> </div> </main> @endsection |
Now that everything is set up, let's put our example to the test by executing the command below:
Open the following URL in your browser: