Download Laravel App
composer create-project --prefer-dist laravel/laravel my-app
C:\xampp\htdocs\laravel>composer create-project --prefer-dist laravel/laravel my-app
Connecting our Database
open .env file root directory.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laraveldb
DB_USERNAME=root
DB_PASSWORD=
Install Auth Scaffold
composer require laravel/ui
C:\xampp\htdocs\laravel\my-app>composer require laravel/ui
generate auth scaffold with bootstrap
php artisan ui bootstrap --auth
C:\xampp\htdocs\laravel\my-app>php artisan ui bootstrap --auth
install npm packages
npm install
C:\xampp\htdocs\laravel\my-app>npm install
built bootstrap CSS
npm run build
C:\xampp\htdocs\laravel\my-app>npm run build
update user migration database/migrations/create_users_table.php
//database/migrations/create_users_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('address')->nullable();
$table->string('profile_image')->nullable();
$table->string('phone')->nullable();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
};
run the migration C:\xampp\htdocs\laravel\my-app>php artisan migrate
app/Models/User.php
//app/Models/User.php
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
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;
protected $fillable = [
'name',
'email',
'phone',
'address',
'profile_image',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
update home controller app/Http/Controllers/HomeController.php
//app/Http/Controllers/HomeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Validator;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
}
public function updateProfile(Request $request)
{
$validated = Validator::make($request->all(), [
'name' => ['required', 'string', 'max:255'],
'phone' => ['required', 'string', 'max:255'],
'address' => ['required', 'string', 'max:255'],
]);
# check if user profile image is null, then validate
if (auth()->user()->profile_image == null) {
$validate_image = Validator::make($request->all(), [
'profile_image' => ['required', 'image', 'max:1000']
]);
# check if their is any error in image validation
if ($validate_image->fails()) {
return response()->json(['code' => 400, 'msg' => $validate_image->errors()->first()]);
}
}
# check if their is any error
if ($validated->fails()) {
return response()->json(['code' => 400, 'msg' => $validated->errors()->first()]);
}
# check if the request has profile image
if ($request->hasFile('profile_image')) {
$imagePath = 'storage/'.auth()->user()->profile_image;
# check whether the image exists in the directory
if (File::exists($imagePath)) {
# delete image
File::delete($imagePath);
}
$profile_image = $request->profile_image->store('profile_images', 'public');
}
# update the user info
auth()->user()->update([
'name' => $request->name,
'phone' => $request->phone,
'address' => $request->address,
'profile_image' => $profile_image ?? auth()->user()->profile_image
]);
return response()->json(['code' => 200, 'msg' => 'profile updated successfully.']);
}
}
resources/views/home.blade.php
//resources/views/home.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Laravel 9 User Profile Update with Image profile upload using jquery ajax</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
Laravel 9 User Profile Update with Image profile upload using Jquery Ajax
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-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">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav me-auto">
</ul>
<!-- 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>
{{ Auth::user()->name }}
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<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>
</div>
</div>
</nav>
<div class="container mt-4">
<form method="POST" enctype="multipart/form-data" id="profile_setup_frm" action="{{ route('update.profile') }}" >
<div class="row">
<div class="col-md-4 border-right">
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
@php($profile_image = auth()->user()->profile_image)
<img class="rounded-circle mt-5" height="250" width="250" src="@if($profile_image == null) {{ asset("storage/profile_images/avatar.png") }} @else {{ asset("storage/$profile_image") }} @endif" id="image_preview_container">
<span class="font-weight-bold">
<input type="file" name="profile_image" id="profile_image" class="form-control">
</span>
</div>
</div>
<div class="col-md-8 border-right">
<div class="p-3 py-5">
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="text-right">Profile Settings</h4>
</div>
<div class="row" id="res"></div>
<div class="row mt-2">
<div class="col-md-6">
<label class="labels">Name</label>
<input type="text" name="name" class="form-control" placeholder="first name" value="{{ auth()->user()->name }}">
</div>
<div class="col-md-6">
<label class="labels">Email</label>
<input type="text" name="email" disabled class="form-control" value="{{ auth()->user()->email }}" placeholder="Email">
</div>
</div>
<div class="row mt-2">
<div class="col-md-6">
<label class="labels">Phone</label>
<input type="text" name="phone" class="form-control" placeholder="Phone Number" value="{{ auth()->user()->phone }}">
</div>
<div class="col-md-6">
<label class="labels">Address</label>
<input type="text" name="address" class="form-control" value="{{ auth()->user()->address }}" placeholder="Address">
</div>
</div>
<div class="mt-5 text-center"><button id="btn" class="btn btn-primary profile-button" type="submit">Save Profile</button></div>
</div>
</div>
</div>
</form>
</div>
<script src="{{ asset('js/profileupdate.js') }}"></script>
</body>
</html>
public/js/profileupdate.js
//public/js/profileupdate.js
$(document).ready(function(){
// image preview
$("#profile_image").change(function(){
let reader = new FileReader();
reader.onload = (e) => {
$("#image_preview_container").attr('src', e.target.result);
}
reader.readAsDataURL(this.files[0]);
})
$("#profile_setup_frm").submit(function(e){
e.preventDefault();
var formData = new FormData(this);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$("#btn").attr("disabled", true);
$("#btn").html("Updating...");
$.ajax({
type:"POST",
url: this.action,
data: formData,
cache:false,
contentType: false,
processData: false,
success: (response) => {
if (response.code == 400) {
let error = '<span class="alert alert-danger">'+response.msg+'</span>';
$("#res").html(error);
$("#btn").attr("disabled", false);
$("#btn").html("Save Profile");
}else if(response.code == 200){
let success = '<span class="alert alert-success">'+response.msg+'</span>';
$("#res").html(success);
$("#btn").attr("disabled", false);
$("#btn").html("Save Profile");
}
}
})
})
})
Routes routes/web.php
//routes/web.php
<?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::post('/updateProfile', [App\Http\Controllers\HomeController::class, 'updateProfile'])->name('update.profile');
https://laravel.com/docs/9.x/filesystem The Public Disk
C:\xampp\htdocs\laravel\my-app>php artisan storage:link
Run C:\xampp\htdocs\laravel\my-app>php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
