Laravel is an excellent PHP framework with many superb features which ease developers’ burden. For example, the built-in authentication alleviates developers’ trouble of making user authentication from the ground up, which is almost a necessity of many web sites.
Only one command to equip the basic authentication:
$ php artisan make:auth
The functionality includes new user registration, user login and reset password.
However, there is one important feature missing: change password.
This article explains the steps to implement the “change password” functionality after the implementation of Laravel basic authentication. It is based on Laravel 5.7.
Few parts added
Adding new functionality concerns as follows:
- model (has created!)
- route
- controller
- view
In this case, model User has been created. We just take care of the remaining three parts:
route
Firstly, we follow the naming convention and put the ‘password
’ prefix before the name of the routes ‘change
’.
routes/web.php
Route::get('password/change','Auth\ChangePasswordController@showChangeForm');
Route::post('password/change','Auth\ChangePasswordController@change')->name('password.change');
controller
The controller named as ‘ChangePasswordController’ under the namespace ‘Auth’ is also follows the naming convention of Laravel authentication. Using artisan command to generate the controller we need.
$ php artisan make:controller Auth/ChangePasswordController
app/Http/Controllers/Auth/ChangePasswordController.php
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class ChangePasswordController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
}
As you can see, the first function we implement in the controller is the __construct()
function. It states the user must be an authenticated user who is qualified to change password.
Two more functions are added as follows:
public function showChangeForm()
public function change()
The showChangeForm()
function just shows a form to change password, while the change()
function does the changing password job.
public function showChangeForm() {
return view('auth.passwords.change');
}
Note that auth.passwords.change
is due to the password related operations are under the directory ‘auth/passwords’.
Here shows the code for the controller as below:
- app/Http/Controllers/Auth/ChangePasswordController.php
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
class ChangePasswordController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
public function showChangeForm() {
return view('auth.passwords.change');
}
public function change(Request $request) {
$current_password = $request->get('current_password');
$new_password = $request->get('new_password');
if (Hash::check($current_password, Auth::user()->password)) {
if (strcmp($current_password, $new_password) != 0) {
$request->validate([
'current_password' => 'required',
'new_password' => 'required|string|min:6|confirmed',
]);
$user = Auth::user();
$user->password = Hash::make($new_password);
$user->save();
return redirect('/')->with('message', ['success', 'Password has been updated!']);
} else {
return redirect()->back()->with('message', ['danger', 'New and current password are the same!']);
}
} else {
return redirect()->back()->with('message', ['danger', 'Password incorrect!']);
}
}
}
view
Now, we copy and modify from login.blade.php
then create a view file change.blade.php
under the directory 'resources/views/auth/passwords`.
- resources/views/auth/passwords/change.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Change Password') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('password.change') }}">
@csrf
<div class="form-group row">
<label for="current_password" class="col-md-4 col-form-label text-md-right">
{{ __('Current Password') }}
</label>
<div class="col-md-6">
<input id="current_password" type="password"
class="form-control{{ $errors->has('current_password') ? ' is-invalid' : '' }}"
name="current_password" value="{{ old('current_password') }}" required autofocus>
@if ($errors->has('current_password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('current_password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="new_password" class="col-md-4 col-form-label text-md-right">
{{ __('New Password') }}
</label>
<div class="col-md-6">
<input id="new_password" type="password"
class="form-control{{ $errors->has('new_password') ? ' is-invalid' : '' }}"
name="new_password" required>
@if ($errors->has('new_password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('new_password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="new_password_confirmation" class="col-md-4 col-form-label text-md-right">
{{ __('Confirm New Password') }}
</label>
<div class="col-md-6">
<input id="new_password_confirmation" type="password"
class="form-control{{ $errors->has('new_password_confirmation') ? ' is-invalid' : '' }}"
name="new_password_confirmation" required>
@if ($errors->has('new_password_confirmation'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('new_password_confirmation') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Change Password') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Note
'new_password' => 'required|string|min:6|confirmed',
Note that in Laravel validation, when ‘confirmed’ validation is activated, the name of the confirmed field must be ‘xxx_confirmation’. For example, the name of the password field is ‘password’, then the name of the confirmed password field has to be ‘password_confirmation’. That is the rule to enable the confirmed validation.