Building a user profile update feature in a Laravel 11 application—where users can modify their username, email, password, mobile number, profile picture, and more—is a staple for modern web applications. Whether you’re working on a personal project or a professional app, this functionality is essential for providing a personalized user experience.
Here’s an engaging guide to help you implement Laravel Update User Profile feature in your Laravel application:
Step 1 – Install Laravel 11
Begin by setting up a new Laravel 11 project using Composer:
composer create-project --prefer-dist laravel/laravel UserProfileApp
Step 2 – Configure the Database
Edit the .env
file to set up your database configuration:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_database_username
DB_PASSWORD=your_database_password
Step 3 – Add Laravel UI Package
Install the Laravel UI package for authentication scaffolding:
composer require laravel/ui
Step 4 – Generate Authentication Scaffolding
Generate the authentication scaffolding with Bootstrap styling:
php artisan ui bootstrap --auth
npm install && npm run dev
Step 5 – Create and Run Migration
Create a migration file to add additional fields to the users
table:
php artisan make:migration add_fields_to_users
Edit the migration file located at database/migrations/_add_fields_to_users.php
and include the following code:
<?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('avatar')->nullable();
$table->string('phone')->nullable();
$table->string('city')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['avatar', 'phone', 'city']);
});
}
};
Apply the migration:
php artisan migrate
Step 6 – Update the User Model
Modify the app/Models/User.php
file to include the new fields:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
'avatar',
'phone',
'city',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
Step 7 – Define Routes
Add routes in routes/web.php
to handle profile update requests:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::get('/profile', [App\Http\Controllers\ProfileController::class, 'index'])->name('user.profile');
Route::post('/profile', [App\Http\Controllers\ProfileController::class, 'store'])->name('user.profile.store');
Step 8 – Create the Controller
Generate a controller for managing profile updates:
php artisan make:controller ProfileController
Edit app/Http/Controllers/ProfileController.php
and implement the update logic:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class ProfileController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the profile edit form.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('profile');
}
/**
* Handle the profile update request.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|max:255',
'confirm_password' => 'required_with:password|same:password',
'avatar' => 'nullable|image',
]);
$data = $request->all();
if ($request->hasFile('avatar')) {
$avatarName = time() . '.' . $request->avatar->getClientOriginalExtension();
$request->avatar->move(public_path('avatars'), $avatarName);
$data['avatar'] = $avatarName;
} else {
unset($data['avatar']);
}
if ($request->filled('password')) {
$data['password'] = Hash::make($data['password']);
} else {
unset($data['password']);
}
auth()->user()->update($data);
return back()->with('success', 'Profile updated successfully.');
}
}
Step 9 – Create the Blade View
Create the profile.blade.php
view in resources/views
and add the following code:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<div class="card-header">{{ __('Profile') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('user.profile.store') }}" enctype="multipart/form-data">
@csrf
@if (session('success'))
<div class="alert alert-success" role="alert">
{{ session('success') }}
</div>
@endif
<div class="row">
<div class="mb-3 col-md-6">
<label for="avatar" class="form-label">Avatar:</label>
<input id="avatar" type="file" class="form-control @error('avatar') is-invalid @enderror" name="avatar">
@error('avatar')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3 col-md-6">
<img src="/avatars/{{ auth()->user()->avatar }}" style="width:80px;margin-top:10px;">
</div>
</div>
<div class="row">
<div class="mb-3 col-md-6">
<label for="name" class="form-label">Name:</label>
<input id="name" type="text" class="form-control" name="name" value="{{ auth()->user()->name }}">
@error('name')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3 col-md-6">
<label for="email" class="form-label">Email:</label>
<input id="email" type="email" class="form-control" name="email" value="{{ auth()->user()->email }}">
@error('email')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row">
<div class="mb-3 col-md-6">
<label for="password" class="form-label">Password:</label>
<input id="password" type="password" class="form-control" name="password">
@error('password')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3 col-md-6">
<label for="confirm_password" class="form-label">Confirm Password:</label>
<input id="confirm_password" type="password" class="form-control" name="confirm_password">
@error('confirm_password')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row">
<div class="mb-3 col-md-6">
<label for="phone" class="form-label">Phone:</label>
<input id="phone" type="text" class="form-control" name="phone" value="{{ auth()->user()->phone }}">
@error('phone')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3 col-md-6">
<label for="city" class="form-label">City:</label>
<input id="city" type="text" class="form-control" name="city" value="{{ auth()->user()->city }}">
@error('city')
<span class="text-danger">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-12 text-center">
<button type="submit" class="btn btn-primary">
{{ __('Update Profile') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Additionally, update the profile link in resources/views/layouts/app.blade.php
:
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ms-auto">
<!-- Authentication Links -->
@guest
@if (Route::has('login'))
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
@endif
@if (Route::has('register'))
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
</li>
@endif
@else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
<img src="/avatars/{{ Auth::user()->avatar }}" style="width: 30px; border-radius: 10%">
{{ Auth::user()->name }}
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<a href="{{ route('user.profile') }}" class="dropdown-item">Profile</a>
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf
</form>
</div>
</li>
@endguest
</ul>
Step 10 – Test the Application
Start the Laravel development server:
php artisan serve
Visit http://127.0.0.1:8000/
in your browser to test the user profile update functionality.