Creating a Forgot and Reset Password Feature in PHP and MySQL Tutorial

In this tutorial, you can learn how to create a Forgot and Reset Password feature in PHP and MySQL Database. This tutorial aims to provide students and beginners with a reference for learning to create and implement useful features of web applications or websites. Here, I will be providing simple web application scripts that demonstrate the creation of an application with Forgot and Reset Password Feature.

What is Forgot and Reset Password?

The Forgot and Reset Password is one of the common and often implemented features of the software or web applications that allows registered users who may forget their account password to retrieve it. The Forgot Password is the way to trigger resetting or retrieving the user's account. Some web applications provide multiple options to retrieve the user account such as sending OTP PIN by email or Text message, answering questions that users selected and provided with an answer to when they created their account, and sending an email with a reset link to allow the users set their new password.

How to create a Forgot and Reset Password Feature in PHP?

To create a Forgot and Reset Password Feature, we can simply develop and implement pages that allow the user to set new passwords or retrieve their accounts. Also, we need to secure these pages so that will only allow real users to access and retrieve the account. Check out the source scripts of a simple web application that I created and provided below to understand it more or to have an idea of how to create a Forgot and Reset Password Feature.

Sample Web Application Source Code

The scripts that I am providing below result in a simple web application that has the following features and functionalities:

  • Page Authentication
  • Login Page
  • Profile Page
  • Forgot Password Page
  • Send Mail with Reset Password Link
  • Reset Password Page

Before we continue to the coding part of this tutorial, please make sure that you have already set up your server or local machine to allow sending emails. For those who are using XAMPP and want to use Gmail SMPT, you can learn to set up sendmail XAMPP package and GMail SMTP by clicking the link.

Let's Get Started

Creating the Database

In your MySQL Server, create a new database named dummy_db. Then, copy and paste the following database schema for the DB table and data. Kindly, change to provided emails with emails that you have access to for testing. All of the user account passwords is password&123

  1. CREATE TABLE `users` (
  2. `id` int(11) NOT NULL,
  3. `fullname` text NOT NULL,
  4. `contact` text NOT NULL,
  5. `email` text NOT NULL,
  6. `password` text NOT NULL,
  7. `about` text NOT NULL
  8.  
  9. INSERT INTO `users` (`id`, `fullname`, `contact`, `email`, `password`, `about`) VALUES
  10. (1, 'Mark Cooper', '09123456798', '[email protected]', '$2y$10$EV6xjIC478dLe.YDxUoaEedj/J.MGsf65ciVfJkknFldlH0SkBxX6', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam fringilla lacus nec velit hendrerit molestie. Ut nec aliquam arcu. Duis ut libero nec risus egestas viverra non ac risus.'),
  11. (2, 'Claire Blake', '09123654456', '[email protected]', '$2y$10$EV6xjIC478dLe.YDxUoaEedj/J.MGsf65ciVfJkknFldlH0SkBxX6', 'Vestibulum sem dui, venenatis eu eleifend nec, placerat ut enim. Phasellus luctus, lectus aliquet ullamcorper vulputate, justo magna fermentum est, vel vulputate tortor augue vel ex.'),
  12. (3, 'John Smith', '09759874562', '[email protected]', '$2y$10$EV6xjIC478dLe.YDxUoaEedj/J.MGsf65ciVfJkknFldlH0SkBxX6', 'Vivamus dictum rutrum dolor, ut pretium mauris tempor elementum. Pellentesque facilisis neque ut efficitur tincidunt.');
  13.  
  14. ALTER TABLE `users`
  15. ADD PRIMARY KEY (`id`);
  16.  
  17. ALTER TABLE `users`

Creating the Database Connection

Next, let's create the PHP file that creates a connection between the application and the database. In your source code directory, create a new PHP file named db-connect.php. Then, copy and paste the script below.

  1. <?php
  2. $host = "localhost";
  3. $username = "root";
  4. $password = "";
  5. $dbname = "dummy_db";
  6.  
  7. try{
  8. $conn = new MySQLi($host, $username, $password, $dbname);
  9. } catch (Exception $e){
  10. die($e->getMessage());
  11. }

Creating the Page Authentication

Next, we will create a PHP script that handles the logged-in and not logged-in users for accessing the web pages. The script below redirects the user to the login page when he is trying to access the home or profile page by logging in first and vice versa. Save the script below as auth.php

  1. <?php
  2. $_self = $_SERVER["PHP_SELF"];
  3. if(stripos($_self, 'index.php')){
  4. if(!isset($_SESSION['id']) || (isset($_SESSION['id']) && $_SESSION['id'] <= 0)){
  5. header('location: login.php');
  6. }
  7. } elseif(stripos($_self, 'login.php') || stripos($_self, 'reset-password.php') || stripos($_self, 'forgot-password.php')){
  8. if(isset($_SESSION['id']) && $_SESSION['id'] > 0){
  9. header('location: index.php');
  10. }
  11. }

Creating the Page Headers

Next, the following script contains the head tag of the web pages. This file is included in each web page so that we don't need to rewrite the script in each page and we can edit only one file for any changes we wanted. Save the file as header.php.

  1. <meta charset="UTF-8">
  2. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  3. <title>Reset Password in PHP</title>
  4. <link rel="stylesheet" href="style.css">
  5. <link rel="preconnect" href="https://fonts.googleapis.com">
  6. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  7. </head>

Creating the Pages Stylesheet

The following file is script is known as style.css. The script contains the web application page stylesheet codes for the design of the page template and some elements.

  1. @import url('https://fonts.googleapis.com/css2?family=Dongle:wght@300;400;700&family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;1,100;1,200;1,300;1,400;1,500;1,600&display=swap" rel="stylesheet');
  2. *{
  3. margin: 0;
  4. padding: 0;
  5. box-sizing: border-box;
  6. font-family: 'Dongle', sans-serif;
  7. font-family: 'Roboto Mono', monospace;
  8. }
  9. ::selection{
  10. color: #fff;
  11. background: #4db2ec;
  12. }
  13. body{
  14. display: flex;
  15. flex-direction: column;
  16. flex-wrap: wrap;
  17. align-items: center;
  18. justify-content: center;
  19. min-height: 100vh;
  20. /* background: #0B2447;
  21.   background-image: linear-gradient(to right, #2E4F4F 0%, #0B2447 100%); */
  22. background-color: #21D4FD;
  23. background-image: linear-gradient(19deg, #21D4FD 0%, #B721FF 100%);
  24.  
  25. padding: 2em 0;
  26. }
  27. .text-center{
  28. text-align:center;
  29. justify-content: center;
  30. }
  31. .mx-auto{
  32. margin: 0 auto;
  33. }
  34. #page-title{
  35. color: #fff;
  36. text-align: center;
  37. font-weight: 500;
  38. }
  39. #title_hr{
  40. width:60px;
  41. border: 2px solid #ffffff;
  42. margin: .35em auto;
  43. }
  44. .container{
  45. margin: 5rem 3rem;
  46. }
  47. /* Text color */
  48. .text-muted{
  49. color: #585858;
  50. }
  51. .input-label{
  52. display: block;
  53. font-weight: 500;
  54. color: #444444;
  55. margin-bottom:.35em
  56. }
  57. /* form input-field */
  58. .input-field{
  59. margin: .5em .35em;
  60. }
  61. /* form input-field */
  62. .input-field input{
  63. padding: .5em 1em;
  64. outline:none;
  65. border: 1px solid #c4c4c4;
  66. width: 100%;
  67. }
  68. .input-field input:focus{
  69. border: 1px solid #0098fd;
  70. box-shadow: 0px 0px 10px #0098fd;
  71. }
  72. .login-btn, .reset-btn{
  73. text-decoration: none;
  74. padding: .5em 1em;
  75. border: none;
  76. background-color: #02a3ee;
  77. color: #fff;
  78. font-weight: 500;
  79. display: block;
  80. margin: .35em auto;
  81. border-radius: 3px;
  82. text-align: center;
  83. min-width: 100px;
  84. cursor: pointer;
  85. }
  86. .login-btn:hover,
  87. .reset-btn:hover,
  88. .login-btn:active,
  89. .reset-btn:active{
  90. background-color: #048eff;
  91. box-shadow: 0px 0px 10px #048eff3b;
  92.  
  93. }
  94. .logout-btn{
  95. text-decoration: none;
  96. padding: .5em 1em;
  97. border: none;
  98. background-color: #f8390a;
  99. color: #fff;
  100. font-weight: 500;
  101. display: block;
  102. margin: .35em auto;
  103. border-radius: 3px;
  104. text-align: center;
  105. min-width: 100px;
  106. cursor: pointer;
  107. }
  108. .logout-btn:hover,
  109. .logout-btn:active{
  110. background-color: #f81a0a;
  111. box-shadow: 0px 0px 10px #f81a0a36;
  112.  
  113. }
  114. /* Login Wrapper */
  115. #login-wrapper{
  116. width: 350px;
  117. margin: 1em auto;
  118. padding: 1em 1.5em;
  119. background-color: #fff;
  120. border: 1px solid #d4d4d4;
  121. box-shadow: 0px 0px 10px #00000069;
  122. }
  123. /* Profile Wrapper */
  124. #profile-wrapper{
  125. width: 400px;
  126. margin: 1em auto;
  127. padding: 1em 1.5em;
  128. background-color: #fff;
  129. border: 1px solid #d4d4d4;
  130. box-shadow: 0px 0px 10px #00000069;
  131. }
  132. .message-success,
  133. .message-error{
  134. width: 100%;
  135. padding: 1em;
  136. margin: 1em .5em;
  137. }
  138. .message-success{
  139. background-color: #04bd60;
  140. color: #d9ffec;
  141. }
  142. .message-error{
  143. background-color: #ff2e12;
  144. color: #f9dbd8;
  145. }
  146.  
  147.  
  148. /* Mobile View */
  149. @media (max-width: 480px){
  150. #login-wrapper{
  151. width: 95%;
  152. }
  153. #profile-wrapper{
  154. width: 95%;
  155. }
  156. }
  157. dl{
  158. margin-bottom: 1.5em;
  159. }
  160. dt{
  161. color: #4e4e4e;
  162. }
  163. dd{
  164. color: #292929;
  165. padding-left: 1em;
  166. }

Creating the web pages

The following scripts are the PHP file scripts of the web pages and the email template of the web application we are building. Each action script such as the login process is written on the same file script of the web page interface. Save the files according to the filename above each script.

login.php

The file contains the page interface and PHP scripts of the web application login feature.

  1. <?php
  2. require_once('auth.php');
  3. require_once('db-connect.php');
  4. if($_SERVER['REQUEST_METHOD'] == 'POST'){
  5. extract($_POST);
  6. $stmt = $conn->prepare("SELECT * FROM `users` where `email` = ?");
  7. $stmt->bind_param('s', $email);
  8. $stmt->execute();
  9. $result = $stmt->get_result();
  10. if($result->num_rows > 0){
  11. $data = $result->fetch_assoc();
  12. if(password_verify($password, $data['password'])){
  13. foreach($data as $k => $v){
  14. if($k != 'password'){
  15. $_SESSION[$k] = $v;
  16. }
  17. }
  18. $_SESSION['msg']['success'] = "You have login successfully.";
  19. header('location: ./');
  20. exit;
  21. }else{
  22. $error = "Incorrect Email or Password";
  23. }
  24. }else{
  25. $error = "Incorrect Email or Password";
  26. }
  27. }
  28. ?>
  29. <!DOCTYPE html>
  30. <html lang="en">
  31. <?php include_once('header.php') ?>
  32. <h1 id="page-title" class="text-center">Login Page</h1>
  33. <hr id="title_hr" class="mx-auto">
  34. <div id="login-wrapper">
  35. <div class="text-muted"><small><em>Please Fill all the required fields</em></small></div>
  36. <?php if(isset($error) && !empty($error)): ?>
  37. <div class="message-error"><?= $error ?></div>
  38. <?php endif; ?>
  39. <?php if(isset($_SESSION['msg']['success']) && !empty($_SESSION['msg']['success'])): ?>
  40. <div class="message-success">
  41. <?php
  42. echo $_SESSION['msg']['success'];
  43. unset($_SESSION['msg']);
  44. ?>
  45. </div>
  46. <?php endif; ?>
  47. <form action="" method="POST">
  48. <div class="input-field">
  49. <label for="email" class="input-label">Email</label>
  50. <input type="email" id="email" name="email" value="<?= $_POST['email'] ?? "" ?>" required="required">
  51. </div>
  52. <div class="input-field">
  53. <label for="password" class="input-label">Password</label>
  54. <input type="password" id="password" name="password" value="<?= $_POST['password'] ?? "" ?>" required="required">
  55. </div>
  56. <div class="input-field ">
  57. <a href="forgot-password.php" tabindex="-1"><small><strong>Forgot Password?</strong></small></a>
  58. </div>
  59. <button class="login-btn">Login</button>
  60. </form>
  61. </div>
  62. </body>
  63. </html>

index.php

This file script contains the page interface of the application home page or the user profile page.

  1. <?php
  2. require_once('auth.php');
  3. require_once('db-connect.php');
  4. ?>
  5. <!DOCTYPE html>
  6. <html lang="en">
  7. <?php include_once('header.php') ?>
  8. <h1 id="page-title" class="text-center">Home Page</h1>
  9. <hr id="title_hr" class="mx-auto">
  10. <div id="profile-wrapper">
  11. <?php if(isset($_SESSION['msg']['success']) && !empty($_SESSION['msg']['success'])): ?>
  12. <div class="message-success">
  13. <?php
  14. echo $_SESSION['msg']['success'];
  15. unset($_SESSION['msg']);
  16. ?>
  17. </div>
  18. <?php endif; ?>
  19. <h2 class="text-center"><strong>Profile</strong></h2>
  20. <hr width="25px" style="margin: .35em auto">
  21. <br>
  22. <dl>
  23. <dt><strong>Fullname:</strong></dt>
  24. <dd><?= $_SESSION['fullname'] ?? "" ?></dd>
  25. <dt><strong>Contact No.:</strong></dt>
  26. <dd><?= $_SESSION['contact'] ?? "" ?></dd>
  27. <dt><strong>Email:</strong></dt>
  28. <dd><?= $_SESSION['email'] ?? "" ?></dd>
  29. <dt><strong>About:</strong></dt>
  30. <dd><?= $_SESSION['about'] ?? "" ?></dd>
  31. </dl>
  32. <a href="logout.php" class="logout-btn">Logout</a>
  33. </div>
  34. </body>
  35. </html>

forgot-password.php

The script below contains the codes that allow the user to enter their account email. The script verifies the provided email if it is registered on the system and if does, the system will generate a reset link and send it to user's email.

  1. <?php
  2. require_once('auth.php');
  3. require_once('db-connect.php');
  4. if($_SERVER['REQUEST_METHOD'] == 'POST'){
  5. extract($_POST);
  6. $stmt = $conn->prepare("SELECT * FROM `users` where `email` = ?");
  7. $stmt->bind_param('s', $email);
  8. $stmt->execute();
  9. $result = $stmt->get_result();
  10. if($result->num_rows > 0){
  11. $data = $result->fetch_assoc();
  12. $email= $data['email'];
  13.  
  14. $subject = "Sample Website - Reset Password";
  15. $message = "";
  16. ob_start();
  17. include("reset_mail-template.php");
  18. $message = ob_get_clean();
  19. // echo $message;exit;
  20. $eol = "\r\n";
  21. // Mail Main Header
  22. $headers = "From: [email protected]" . $eol;
  23. $headers .= "Reply-To: [email protected]" . $eol;
  24. $headers .= "To: <{$email}>" . $eol;
  25. $headers .= "MIME-Version: 1.0" . $eol;
  26. $headers .= "Content-Type: text/html; charset=iso-8859-1" . $eol;
  27. try{
  28. mail($email, $subject, $message, $headers);
  29. $_SESSION['msg']['success'] = "We have sent you an email to reset your password.";
  30. header('location: login.php');
  31. exit;
  32. }catch(Exception $e){
  33. throw new ErrorException($e->getMessage());
  34. exit;
  35. }
  36. ?>
  37. <?php
  38. }else{
  39. $error = "Email is not registered.";
  40. }
  41. }
  42. ?>
  43. <!DOCTYPE html>
  44. <html lang="en">
  45. <?php include_once('header.php') ?>
  46. <h1 id="page-title" class="text-center">Forgot Password Page</h1>
  47. <hr id="title_hr" class="mx-auto">
  48. <div id="login-wrapper">
  49. <div class="text-muted"><small><em>Please Fill all the required fields</em></small></div>
  50. <?php if(isset($error) && !empty($error)): ?>
  51. <div class="message-error"><?= $error ?></div>
  52. <?php endif; ?>
  53. <form action="" method="POST">
  54. <div class="input-field">
  55. <label for="email" class="input-label">Email</label>
  56. <input type="email" id="email" name="email" value="<?= $_POST['email'] ?? "" ?>" required="required">
  57. </div>
  58. <div class="input-field ">
  59. <a href="login.php" tabindex="-1"><small><strong>Go back to login page</strong></small></a>
  60. </div>
  61. <button class="login-btn">Reset Password</button>
  62. </form>
  63. </div>
  64. </body>
  65. </html>

reset_mail-template.php

The following script is the reset password email template that I used for this tutorial. The template I use was taken from Unlayer Free Template.

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
  3. <!--[if gte mso 9]>
  4. <xml>
  5. <o:OfficeDocumentSettings>
  6. <o:AllowPNG/>
  7. <o:PixelsPerInch>96</o:PixelsPerInch>
  8. </o:OfficeDocumentSettings>
  9. </xml>
  10. <![endif]-->
  11. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  12. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  13. <meta name="x-apple-disable-message-reformatting">
  14. <!--[if !mso]><!--><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]-->
  15.  
  16. <style type="text/css">
  17. @media only screen and (min-width: 620px) {
  18. .u-row {
  19. width: 600px !important;
  20. }
  21. .u-row .u-col {
  22. vertical-align: top;
  23. }
  24.  
  25. .u-row .u-col-100 {
  26. width: 600px !important;
  27. }
  28.  
  29. }
  30.  
  31. @media (max-width: 620px) {
  32. .u-row-container {
  33. max-width: 100% !important;
  34. padding-left: 0px !important;
  35. padding-right: 0px !important;
  36. }
  37. .u-row .u-col {
  38. min-width: 320px !important;
  39. max-width: 100% !important;
  40. display: block !important;
  41. }
  42. .u-row {
  43. width: 100% !important;
  44. }
  45. .u-col {
  46. width: 100% !important;
  47. }
  48. .u-col > div {
  49. margin: 0 auto;
  50. }
  51. }
  52. body {
  53. margin: 0;
  54. padding: 0;
  55. }
  56.  
  57. table,
  58. tr,
  59. td {
  60. vertical-align: top;
  61. border-collapse: collapse;
  62. }
  63.  
  64. p {
  65. margin: 0;
  66. }
  67.  
  68. .ie-container table,
  69. .mso-container table {
  70. table-layout: fixed;
  71. }
  72.  
  73. * {
  74. line-height: inherit;
  75. }
  76.  
  77. a[x-apple-data-detectors='true'] {
  78. color: inherit !important;
  79. text-decoration: none !important;
  80. }
  81.  
  82. table, td { color: #000000; } #u_body a { color: #0000ee; text-decoration: underline; } @media (max-width: 480px) { #u_content_image_1 .v-container-padding-padding { padding: 40px 10px 10px !important; } #u_content_image_1 .v-src-width { width: auto !important; } #u_content_image_1 .v-src-max-width { max-width: 50% !important; } #u_content_heading_1 .v-container-padding-padding { padding: 10px 10px 20px !important; } #u_content_heading_1 .v-font-size { font-size: 22px !important; } #u_content_heading_2 .v-container-padding-padding { padding: 40px 10px 10px !important; } #u_content_text_2 .v-container-padding-padding { padding: 10px !important; } #u_content_heading_3 .v-container-padding-padding { padding: 10px !important; } #u_content_button_1 .v-container-padding-padding { padding: 30px 10px 40px !important; } #u_content_button_1 .v-size-width { width: 65% !important; } #u_content_social_1 .v-container-padding-padding { padding: 40px 10px 10px !important; } #u_content_text_deprecated_1 .v-container-padding-padding { padding: 10px 10px 20px !important; } #u_content_image_2 .v-container-padding-padding { padding: 20px 10px 40px !important; } }
  83. </style>
  84.  
  85.  
  86.  
  87. <!--[if !mso]><!--><link href="https://fonts.googleapis.com/css?family=Raleway:400,700&display=swap" rel="stylesheet" type="text/css"><!--<![endif]-->
  88.  
  89. </head>
  90.  
  91. <body class="clean-body u_body" style="margin: 0;padding: 0;-webkit-text-size-adjust: 100%;background-color: #f9f9ff;color: #000000">
  92. <!--[if IE]><div class="ie-container"><![endif]-->
  93. <!--[if mso]><div class="mso-container"><![endif]-->
  94. <table id="u_body" style="border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;min-width: 320px;Margin: 0 auto;background-color: #f9f9ff;width:100%" cellpadding="0" cellspacing="0">
  95. <tr style="vertical-align: top">
  96. <td style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
  97. <!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center" style="background-color: #f9f9ff;"><![endif]-->
  98.  
  99.  
  100. <div class="u-row-container" style="padding: 0px;background-color: transparent">
  101. <div class="u-row" style="Margin: 0 auto;min-width: 320px;max-width: 600px;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: transparent;">
  102. <div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
  103. <!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: transparent;"><![endif]-->
  104.  
  105. <!--[if (mso)|(IE)]><td align="center" width="600" style="background-color: #ffffff;width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
  106. <div class="u-col u-col-100" style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
  107. <div style="background-color: #ffffff;height: 100%;width: 100% !important;">
  108. <!--[if (!mso)&(!IE)]><!--><div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;"><!--<![endif]-->
  109.  
  110. <table id="u_content_image_1" style="font-family:'Raleway',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
  111. <tr>
  112. <td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:60px 10px 10px;font-family:'Raleway',sans-serif;" align="left">
  113.  
  114. <table width="100%" cellpadding="0" cellspacing="0" border="0">
  115. <tr>
  116. <td style="padding-right: 0px;padding-left: 0px;" align="center">
  117.  
  118. <img align="center" border="0" src="https://i.ibb.co/nDLWkZm/image-6.png" alt="image" title="image" style="outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: inline-block !important;border: none;height: auto;float: none;width: 35%;max-width: 203px;" width="203" class="v-src-width v-src-max-width"/>
  119.  
  120. </td>
  121. </tr>
  122.  
  123. </td>
  124. </tr>
  125. </tbody>
  126.  
  127. <table id="u_content_heading_1" style="font-family:'Raleway',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
  128. <tr>
  129. <td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:10px 10px 30px;font-family:'Raleway',sans-serif;" align="left">
  130.  
  131. <h1 class="v-font-size" style="margin: 0px; line-height: 140%; text-align: center; word-wrap: break-word; font-size: 28px; font-weight: 400;"><strong>Forget password ?</strong></h1>
  132.  
  133. </td>
  134. </tr>
  135. </tbody>
  136.  
  137. <!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
  138. </div>
  139. </div>
  140. <!--[if (mso)|(IE)]></td><![endif]-->
  141. <!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
  142. </div>
  143. </div>
  144. </div>
  145.  
  146.  
  147.  
  148. <div class="u-row-container" style="padding: 0px;background-color: transparent">
  149. <div class="u-row" style="Margin: 0 auto;min-width: 320px;max-width: 600px;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: transparent;">
  150. <div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
  151. <!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: transparent;"><![endif]-->
  152.  
  153. <!--[if (mso)|(IE)]><td align="center" width="600" style="background-color: #ffffff;width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;" valign="top"><![endif]-->
  154. <div class="u-col u-col-100" style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
  155. <div style="background-color: #ffffff;height: 100%;width: 100% !important;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;">
  156. <!--[if (!mso)&(!IE)]><!--><div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;"><!--<![endif]-->
  157.  
  158. <table id="u_content_heading_2" style="font-family:'Raleway',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
  159. <tr>
  160. <td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:40px 60px 10px;font-family:'Raleway',sans-serif;" align="left">
  161.  
  162. <h1 class="v-font-size" style="margin: 0px; line-height: 140%; text-align: left; word-wrap: break-word; font-size: 16px; font-weight: 400;">If you've lost your password or wish to reset it, use the link below to get started:</h1>
  163.  
  164. </td>
  165. </tr>
  166. </tbody>
  167.  
  168. <table id="u_content_text_2" style="font-family:'Raleway',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
  169. <tr>
  170. <td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:10px 60px;font-family:'Raleway',sans-serif;" align="left">
  171.  
  172. <div class="v-font-size" style="font-size: 14px; color: #1386e5; line-height: 140%; text-align: left; word-wrap: break-word;">
  173. <p style="line-height: 140%;"><span style="text-decoration: underline; line-height: 19.6px;"><span style="line-height: 19.6px;"><strong>
  174. <a href="http://localhost/php-reset-password/reset-password.php?uid=<?= md5($data['id']) ?>">http://localhost/php-reset-password/reset-password.php?uid=<?= md5($data['id']) ?></a>
  175. </strong></span></span></p>
  176. </div>
  177.  
  178. </td>
  179. </tr>
  180. </tbody>
  181.  
  182. <table id="u_content_heading_3" style="font-family:'Raleway',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
  183. <tr>
  184. <td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:10px 60px;font-family:'Raleway',sans-serif;" align="left">
  185.  
  186. <h1 class="v-font-size" style="margin: 0px; line-height: 140%; text-align: left; word-wrap: break-word; font-size: 14px; font-weight: 400;">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation.Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation.</h1>
  187.  
  188. </td>
  189. </tr>
  190. </tbody>
  191.  
  192. <table id="u_content_button_1" style="font-family:'Raleway',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
  193. <tr>
  194. <td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:30px 10px 40px;font-family:'Raleway',sans-serif;" align="left">
  195.  
  196. <!--[if mso]><style>.v-button {background: transparent !important;}</style><![endif]-->
  197. <div align="center">
  198. <!--[if mso]><v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="https://www.unlayer.com" style="height:37px; v-text-anchor:middle; width:220px;" arcsize="67.5%" stroke="f" fillcolor="#fdb441"><w:anchorlock/><center style="color:#000000;font-family:'Raleway',sans-serif;"><![endif]-->
  199. <a href="http://localhost/php-reset-password/reset-password.php?uid=<?= md5($data['id']) ?>" target="_blank" class="v-button v-size-width v-font-size" style="box-sizing: border-box;display: inline-block;font-family:'Raleway',sans-serif;text-decoration: none;-webkit-text-size-adjust: none;text-align: center;color: #000000; background-color: #fdb441; border-radius: 25px;-webkit-border-radius: 25px; -moz-border-radius: 25px; width:38%; max-width:100%; overflow-wrap: break-word; word-break: break-word; word-wrap:break-word; mso-border-alt: none;font-size: 14px;">
  200. <span style="display:block;padding:10px 20px;line-height:120%;"><span style="line-height: 16.8px;">Reset Your Password</span></span>
  201. </a>
  202. <!--[if mso]></center></v:roundrect><![endif]-->
  203. </div>
  204.  
  205. </td>
  206. </tr>
  207. </tbody>
  208.  
  209. <!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
  210. </div>
  211. </div>
  212. <!--[if (mso)|(IE)]></td><![endif]-->
  213. <!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
  214. </div>
  215. </div>
  216. </div>
  217.  
  218.  
  219.  
  220. <div class="u-row-container" style="padding: 0px;background-color: transparent">
  221. <div class="u-row" style="Margin: 0 auto;min-width: 320px;max-width: 600px;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: transparent;">
  222. <div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
  223. <!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: transparent;"><![endif]-->
  224.  
  225. <!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;" valign="top"><![endif]-->
  226. <div class="u-col u-col-100" style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
  227. <div style="height: 100%;width: 100% !important;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;">
  228. <!--[if (!mso)&(!IE)]><!--><div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;"><!--<![endif]-->
  229.  
  230. <!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
  231. </div>
  232. </div>
  233. <!--[if (mso)|(IE)]></td><![endif]-->
  234. <!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
  235. </div>
  236. </div>
  237. </div>
  238.  
  239.  
  240. <!--[if (mso)|(IE)]></td></tr></table><![endif]-->
  241. </td>
  242. </tr>
  243. </tbody>
  244. </table>
  245. <!--[if mso]></div><![endif]-->
  246. <!--[if IE]></div><![endif]-->
  247. </body>
  248.  
  249. </html>
  250.  

reset-password.php

The script below contains the page interface for setting a new password for the user and the PHP script that update the password.

  1. <?php
  2. require_once('auth.php');
  3. require_once('db-connect.php');
  4. if($_SERVER['REQUEST_METHOD'] == 'POST'){
  5. extract($_POST);
  6. if($new_password !== $confirm_password){
  7. $error = "Password does not match.";
  8. }else{
  9. $uid = $_GET['uid'] ?? "";
  10. $stmt = $conn->prepare("SELECT * FROM `users` where md5(`id`) = ?");
  11. $stmt->bind_param('s', $uid);
  12. $stmt->execute();
  13. $result = $stmt->get_result();
  14. if($result->num_rows > 0){
  15. $data = $result->fetch_assoc();
  16. $password = password_hash($new_password, PASSWORD_DEFAULT);
  17. $update = $conn->query("UPDATE `users` set `password` = '{$password}'");
  18. if($update){
  19. $_SESSION['msg']['success'] = "New Password has been saved successfully.";
  20. header('location:login.php');
  21. exit;
  22. }else{
  23. $error = 'Password has failed to update.';
  24. }
  25. }else{
  26. $error = "User is registered on this website.";
  27. }
  28. }
  29. }
  30. ?>
  31. <!DOCTYPE html>
  32. <html lang="en">
  33. <?php include_once('header.php') ?>
  34. <h1 id="page-title" class="text-center">Reset Password</h1>
  35. <hr id="title_hr" class="mx-auto">
  36. <div id="login-wrapper">
  37. <div class="text-muted"><small><em>Please Fill all the required fields</em></small></div>
  38. <?php if(isset($error) && !empty($error)): ?>
  39. <div class="message-error"><?= $error ?></div>
  40. <?php endif; ?>
  41. <?php if(isset($_SESSION['msg']['success']) && !empty($_SESSION['msg']['success'])): ?>
  42. <div class="message-success">
  43. <?php
  44. echo $_SESSION['msg']['success'];
  45. unset($_SESSION['msg']);
  46. ?>
  47. </div>
  48. <?php endif; ?>
  49. <form action="" method="POST">
  50. <div class="input-field">
  51. <label for="new_password" class="input-label">New Password</label>
  52. <input type="password" id="new_password" name="new_password" value="<?= $_POST['new_password'] ?? "" ?>" autofocus required="required">
  53. </div>
  54. <div class="input-field">
  55. <label for="confirm_password" class="input-label">Confirm New Password</label>
  56. <input type="password" id="confirm_password" name="confirm_password" value="<?= $_POST['confirm_password'] ?? "" ?>" required="required">
  57. </div>
  58. <button class="reset-btn">Reset Password</button>
  59. </form>
  60. </div>
  61. </body>
  62. </html>

Creating the Logout Script

Lastly, here's the PHP script that contains the codes for destroying the user session on the application. Save the file script as logout.php.

  1. <?php
  2. header('location: login.php');

Snapshots

Here are some snapshots of the overall result of the scripts I have provided above.

Login Page

Forgot and Reset Password in PHP and MySQL

Home/Profile Page

Forgot and Reset Password in PHP and MySQL

Forgot Password

Forgot and Reset Password in PHP and MySQL

Sample Email with Reset Link

Forgot and Reset Password in PHP and MySQL

Reset Password

Forgot and Reset Password in PHP and MySQL

There you go! I have also provided the complete source code zip file of the web application scripts that I provided and it is free to download. The download button is located below this tutorial's content. Feel free to download and modify the source code the way you wanted to enhance your programming capabilities.

DEMO VIDEO

That's it! I hope this Creating a Forgot and Reset Password Feature in PHP and MySQL Tutorial will help you with what you are looking for and will be useful for your current and future PHP Projects.

Explore more on this website for more Tutorials and Free Source Codes.

Happy Coding =)

Comments

Add new comment