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