Forgot password recovery feature is mandatory for the login system. It helps the user to update account password which they have forgotten. Using forgot password link user can easily reset their account password. In this tutorial, we’ll show you the forgot password recovery process and create a script to implement forgot password email functionality in PHP Login System.
Our previous PHP Login System tutorial had provided a guide to implementing user registration and login system in PHP. Now we’ll extend that PHP login script with forgot password functionality with PHP and MySQL. Also, we’ll show you how can send reset password link via email to the user. Before you begin with this forgot password recovery tutorial, we suggest go through the previous PHP login system tutorial first.
Here the files list that is used in forgot password recovery process.
user.php
– handle database related worksuserAccount.php
– handle forgot password, reset password, and email sending.index.php
– display login form with forgot password link.forgotPassword.php
– display forgot password form.resetPassword.php
– display reset password form.style.css
– styling login, forgot, and reset form.To store the user details you already have a users
table in the MySQL database. Now add a column named forgot_pass_identity
to user table.
ALTER TABLE `users` ADD `forgot_pass_identity` VARCHAR(32) NOT NULL AFTER `phone`;
Entire users
table SQL will like the following.
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `first_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `last_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `phone` varchar(15) COLLATE utf8_unicode_ci NOT NULL, `forgot_pass_identity` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
User Class handles all the database related works, like get, insert, update user data. This class has extended with one method (update()
) for update forgot password identity code in the users
table.
<?php
/*
* User Class
* This class is used for database related (connect fetch, and insert) operations
* @author CodexWorld.com
* @url http://www.codexworld.com
* @license http://www.codexworld.com/license
*/
class User{
private $dbHost = "localhost";
private $dbUsername = "root";
private $dbPassword = "";
private $dbName = "codexworld";
private $userTbl = "users";
public function __construct(){
if(!isset($this->db)){
// Connect to the database
$conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
if($conn->connect_error){
die("Failed to connect with MySQL: " . $conn->connect_error);
}else{
$this->db = $conn;
}
}
}
/*
* Returns rows from the database based on the conditions
* @param string name of the table
* @param array select, where, order_by, limit and return_type conditions
*/
public function getRows($conditions = array()){
$sql = 'SELECT ';
$sql .= array_key_exists("select",$conditions)?$conditions['select']:'*';
$sql .= ' FROM '.$this->userTbl;
if(array_key_exists("where",$conditions)){
$sql .= ' WHERE ';
$i = 0;
foreach($conditions['where'] as $key => $value){
$pre = ($i > 0)?' AND ':'';
$sql .= $pre.$key." = '".$value."'";
$i++;
}
}
if(array_key_exists("order_by",$conditions)){
$sql .= ' ORDER BY '.$conditions['order_by'];
}
if(array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){
$sql .= ' LIMIT '.$conditions['start'].','.$conditions['limit'];
}elseif(!array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){
$sql .= ' LIMIT '.$conditions['limit'];
}
$result = $this->db->query($sql);
if(array_key_exists("return_type",$conditions) && $conditions['return_type'] != 'all'){
switch($conditions['return_type']){
case 'count':
$data = $result->num_rows;
break;
case 'single':
$data = $result->fetch_assoc();
break;
default:
$data = '';
}
}else{
if($result->num_rows > 0){
while($row = $result->fetch_assoc()){
$data[] = $row;
}
}
}
return !empty($data)?$data:false;
}
/*
* Insert data into the database
* @param string name of the table
* @param array the data for inserting into the table
*/
public function insert($data){
if(!empty($data) && is_array($data)){
$columns = '';
$values = '';
$i = 0;
if(!array_key_exists('created',$data)){
$data['created'] = date("Y-m-d H:i:s");
}
if(!array_key_exists('modified',$data)){
$data['modified'] = date("Y-m-d H:i:s");
}
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$columns .= $pre.$key;
$values .= $pre."'".$val."'";
$i++;
}
$query = "INSERT INTO ".$this->userTbl." (".$columns.") VALUES (".$values.")";
$insert = $this->db->query($query);
return $insert?$this->db->insert_id:false;
}else{
return false;
}
}
/*
* Update data into the database
* @param string name of the table
* @param array the data for inserting into the table
*/
public function update($data, $conditions){
if(!empty($data) && is_array($data) && !empty($conditions)){
//prepare columns and values sql
$cols_vals = '';
$i = 0;
if(!array_key_exists('modified',$data)){
$data['modified'] = date("Y-m-d H:i:s");
}
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$cols_vals .= $pre.$key." = '".$val."'";
$i++;
}
//prepare where conditions
$whereSql = '';
$ci = 0;
foreach($conditions as $key => $value){
$pre = ($ci > 0)?' AND ':'';
$whereSql .= $pre.$key." = '".$value."'";
$ci++;
}
//prepare sql query
$query = "UPDATE ".$this->userTbl." SET ".$cols_vals." WHERE ".$whereSql;
//update data
$update = $this->db->query($query);
return $update?true:false;
}else{
return false;
}
}
}
This file controls the registration, login, logout, forgot password, and reset password request. This script has extended with two requests forgotSubmit
and resetSubmit
. Also, the email sending functionality is added in forgotSubmit request to send the email with reset password link to the user.
<?php
//start session
session_start();
//load and initialize user class
include 'user.php';
$user = new User();
if(isset($_POST['forgotSubmit'])){
//check whether email is empty
if(!empty($_POST['email'])){
//check whether user exists in the database
$prevCon['where'] = array('email'=>$_POST['email']);
$prevCon['return_type'] = 'count';
$prevUser = $user->getRows($prevCon);
if($prevUser > 0){
//generat unique string
$uniqidStr = md5(uniqid(mt_rand()));;
//update data with forgot pass code
$conditions = array(
'email' => $_POST['email']
);
$data = array(
'forgot_pass_identity' => $uniqidStr
);
$update = $user->update($data, $conditions);
if($update){
$resetPassLink = 'http://codexworld.com/resetPassword.php?fp_code='.$uniqidStr;
//get user details
$con['where'] = array('email'=>$_POST['email']);
$con['return_type'] = 'single';
$userDetails = $user->getRows($con);
//send reset password email
$to = $userDetails['email'];
$subject = "Password Update Request";
$mailContent = 'Dear '.$userDetails['first_name'].',
<br/>Recently a request was submitted to reset a password for your account. If this was a mistake, just ignore this email and nothing will happen.
<br/>To reset your password, visit the following link: <a href="'.$resetPassLink.'">'.$resetPassLink.'</a>
<br/><br/>Regards,
<br/>CodexWorld';
//set content-type header for sending HTML email
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
//additional headers
$headers .= 'From: CodexWorld<sender@example.com>' . "\r\n";
//send email
mail($to,$subject,$mailContent,$headers);
$sessData['status']['type'] = 'success';
$sessData['status']['msg'] = 'Please check your e-mail, we have sent a password reset link to your registered email.';
}else{
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'Some problem occurred, please try again.';
}
}else{
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'Given email is not associated with any account.';
}
}else{
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'Enter email to create a new password for your account.';
}
//store reset password status into the session
$_SESSION['sessData'] = $sessData;
//redirect to the forgot pasword page
header("Location:forgotPassword.php");
}elseif(isset($_POST['resetSubmit'])){
$fp_code = '';
if(!empty($_POST['password']) && !empty($_POST['confirm_password']) && !empty($_POST['fp_code'])){
$fp_code = $_POST['fp_code'];
//password and confirm password comparison
if($_POST['password'] !== $_POST['confirm_password']){
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'Confirm password must match with the password.';
}else{
//check whether identity code exists in the database
$prevCon['where'] = array('forgot_pass_identity' => $fp_code);
$prevCon['return_type'] = 'single';
$prevUser = $user->getRows($prevCon);
if(!empty($prevUser)){
//update data with new password
$conditions = array(
'forgot_pass_identity' => $fp_code
);
$data = array(
'password' => md5($_POST['password'])
);
$update = $user->update($data, $conditions);
if($update){
$sessData['status']['type'] = 'success';
$sessData['status']['msg'] = 'Your account password has been reset successfully. Please login with your new password.';
}else{
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'Some problem occurred, please try again.';
}
}else{
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'You does not authorized to reset new password of this account.';
}
}
}else{
$sessData['status']['type'] = 'error';
$sessData['status']['msg'] = 'All fields are mandatory, please fill all the fields.';
}
//store reset password status into the session
$_SESSION['sessData'] = $sessData;
$redirectURL = ($sessData['status']['type'] == 'success')?'index.php':'resetPassword.php?fp_code='.$fp_code;
//redirect to the login/reset pasword page
header("Location:".$redirectURL);
}
Note that:
Don’t forget to change the email content, from address, and website base URL in $resetPassLink
as per your project requirement.
A forgot password link is added in the existing login form for navigating user to forgot password form.
<div class="container"> <form action="userAccount.php" method="post"> <input type="email" name="email" placeholder="EMAIL" required=""> <input type="password" name="password" placeholder="PASSWORD" required=""> <div class="send-button"> <input type="submit" name="loginSubmit" value="LOGIN"> </div> <a href="forgotPassword.php">Forgot password?</a> </form> </div>
A form displays to collect the account email for identifying user account. The form is submitted to the userAccount.php
file with a forgotSubmit
request.
<?php
session_start();
$sessData = !empty($_SESSION['sessData'])?$_SESSION['sessData']:'';
if(!empty($sessData['status']['msg'])){
$statusMsg = $sessData['status']['msg'];
$statusMsgType = $sessData['status']['type'];
unset($_SESSION['sessData']['status']);
}
?> <h2>Enter the Email of Your Account to Reset New Password</h2> <?php echo !empty($statusMsg)?'<p class="'.$statusMsgType.'">'.$statusMsg.'</p>':''; ?> <div class="container"> <div class="regisFrm"> <form action="userAccount.php" method="post"> <input type="email" name="email" placeholder="EMAIL" required=""> <div class="send-button"> <input type="submit" name="forgotSubmit" value="CONTINUE"> </div> </form> </div> </div>
This script is loaded when the user clicks on the reset password link in the mail. A form will appear to update account password and the form is submitted to the userAccount.php
file with a resetSubmit
request.
<?php
session_start();
$sessData = !empty($_SESSION['sessData'])?$_SESSION['sessData']:'';
if(!empty($sessData['status']['msg'])){
$statusMsg = $sessData['status']['msg'];
$statusMsgType = $sessData['status']['type'];
unset($_SESSION['sessData']['status']);
}
?> <h2>Reset Your Account Password</h2> <?php echo !empty($statusMsg)?'<p class="'.$statusMsgType.'">'.$statusMsg.'</p>':''; ?> <div class="container"> <div class="regisFrm"> <form action="userAccount.php" method="post"> <input type="password" name="password" placeholder="PASSWORD" required=""> <input type="password" name="confirm_password" placeholder="CONFIRM PASSWORD" required=""> <div class="send-button"> <input type="hidden" name="fp_code" value="<?php echo $_REQUEST['fp_code']; ?>"/> <input type="submit" name="resetSubmit" value="RESET PASSWORD"> </div> </form> </div> </div>
No new CSS code are added to implement forgot password functionality. The same CSS file is included from our login system.
.container { width: 40%; margin: 0 auto; background-color: #f7f7f7; color: #757575; font-family: 'Raleway', sans-serif; text-align: left; padding: 30px; } h2 { font-size: 30px; font-weight: 600; margin-bottom: 10px; } .container p { font-size: 18px; font-weight: 500; margin-bottom: 20px; } .regisFrm input[type="text"], .regisFrm input[type="email"], .regisFrm input[type="password"] { width: 94.5%; padding: 10px; margin: 10px 0; outline: none; color: #000; font-weight: 500; font-family: 'Roboto', sans-serif; } .send-button { text-align: center; margin-top: 20px; } .send-button input[type="submit"] { padding: 10px 0; width: 60%; font-family: 'Roboto', sans-serif; font-size: 18px; font-weight: 500; border: none; outline: none; color: #FFF; background-color: #2196F3; cursor: pointer; } .send-button input[type="submit"]:hover { background-color: #055d54; } a.logout{float: right;} p.success{color:#34A853;} p.error{color:#EA4335;}
Hope this tutorial will help you to implement forgot password recovery system with reset email sending feature. Here we’ve tried to extend our previous login system script with simple forgot password functionality. To get the login system and forgot password functionality script together, download the source code.
Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request
I am using your reg/login/PWreset. Every thing work great! Thank you! I was wondering how to send an auto email response to the user after they register? Something similiar to the php mailer code utilized by the pw reset. I just want to send the user a thanks for registering No-reply email.
Thank you.
This is Awesome. It works fine for me. Looking forward many more projects. Thank you so much.
How would I do to confirm user registration via email, ie confirm that the email is valid during registration?
Please can you tell me how to make a page accessible to logged in users only.
I think there should be some php code I can put at the top of a page that makes it only accessible by someone who has logged in, or, if they are not logged in, send them back to the login page.
Any help would be appreciated
Add the following code at the top of the script where you want to add the restriction.
Dear Coder tank you very much for this very useful article!!!
One question. After registration and login, is it possible to show user name and logout button at the top of every other website page?
All other pages are simple html pages. Thank you!!!
Hi – I was wondering – where do you include the user.php file that creates the DB connection?
The
user.php
file needs to be included in theuserAccount.php
file.Hey i am having some sort of problem i dont get email when ii try to reset the password. Please help me
Check whether you have set the proper from address. Also, check the spam folder of the receiver email. To avoid the spamming related issue, send email via SMTP server – https://www.codexworld.com/send-html-email-php-gmail-smtp-phpmailer/
Thank u so much.. 🙂
thank you !!! really helped me alot. An ajax version will be a nice to have on the future.
Hi!
Could it be possible somehow to combine your three great scripts? The User Registration, The Simple Cart and the Paypal Checkout. I have under 10 products, all services and this would be more than enough for me. Something like Prestashop would be crazy.
Best Regards
Anders Yuran
Heay! CodexWorld Team You Are Doing Great Job.
Can You Create a Full Login And Register System With php And mysql with all features. Like,
1) Mail Verification,
2) Password Reset
3) OTP System with SMS OR E-mail.
4) Full Featured Register form.
( I Know your team already created fantastic post about this stuff but i want all stuffs in one project. it’s difficult for me to join all stuffs in one project. because i’m going throw step-by-step and biggest problem is i’m noob in web development )
Hoping for Your Favourable Response.
Best Regard,
Harshil Patel
We’ll try to publish your requested tutorial soon.
Can you make one where it requires email verification
@Josh Of Course, we’ll extend this PHP Login System script with email verification. Probably it will be published on next week, to get notified subscribe our newsletter.