Laravel Image Upload Made Easy
Today, I will show you guys how to add Laravel Image Upload functionality into your application with validation. This one will be a step by step guide, by the end of this post you will familiarize how to upload an image in Laravel.
Uploading the image in Laravel is very easy! So if you are beginners then you can do that simply. Laravel provides a very simple way to create file uploading with proper validation like max file size 2mb, file extension should be jpeg, png, jpg, gif or SVG etc.
In this post, I will walk you through how we can add the profile image to Laravel’s default authentication which comes out of the box.
By the end of this post, you will have a working example like below.
So let’s start.
Application Setup
I assume, you already have fresh Laravel project, if not go and create with below command.
composer create-project laravel/laravel LaravelImageUpload
Now, open .env
file which is located int the root of your LaravelImageUpload project folder. Update the database credentials with your ones.
Once you have connected a database to Laravel, run below command to generate default Laravel’s authentication scaffolding.
php artisan make:auth
Once you have generated the scaffold, we are ready to start.
Updating Migration File
Laravel provides you a User model and migration for this model by default. Go to database/migrations
folder and open 2014_10_12_000000_create_users_table file.
We will be uploading a profile image for currently authenticated user, so we need to add an extra field in which we will store the image file path. Update the up()
method with below one:
public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('profile_image')->nullable(); // our profile image field $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); }
As you have noticed that, we have added a new field called profile_image and set its type to string. Notice that we have added a nullable()
flag to new fields to keep this image uploading optional for users.
Once you have updated your migration, run below command to create all your migrations.
php artisan migrate
Now if you, check your database you will be able to see that Laravel will create two tables called users and password_resets.
Now it’s time to update our User mode. Open app/User.php
file and add profile_image
to $fillable array.
protected $fillable = ['name', 'email', 'password', 'profile_image'];
Also we will add a new accessor method to get the user’s profile image like so auth()->user()->image
instead of using profile_image
field. So add below code within User class.
public function getImageAttribute() { return $this->profile_image; }
Profile Routes
After migrating tables and updating User model, now we need to setup a new page with form where we will be able to upload image. So for that create two routes in your web.php
routes file. Like so:
Route::get('/profile', 'ProfileController@index')->name('profile'); Route::post('/profile/update', 'ProfileController@updateProfile')->name('profile.update');
Profile Controller
As you have noticed that we have used ProfileController in above routes, so run below command to create a new controller.
php artisan make:controller ProfileController
Now open your newly created controller and update with below code:
namespace App\Http\Controllers; use Illuminate\Http\Request; class ProfileController extends Controller { public function __construct() { $this->middleware('auth'); } public function index() { return view('auth.profile'); } }
As you have seen in the __construct() method we have set up the middleware so only authenticated users will be able to update their profile.
In index()
method we are just loading a new view called profile
which is residing inside auth folder generated by Laravel.
Profile Blade Templates
Above code example is just bootstrap template with a form to upload an image. In form’s action we have added {{ route('profile.update') }}
route, so when we will submit this form it will hit that route.
enctype
in the form declaration which very important for uploading files. Without this your form will not upload any file.Next, we have a input field for user name and loading it’s current value using authentication helper like this auth()->user()->name
.
Next, we have a input field for user email and loading its value in value
attribute. I’m keeping this field disabled so that email change is not possible.
Now, we need to add a drop-down menu for the currently authenticated user to access the profile page. For that in your resources/views/layouts/app.blade.php
file add below line of code just before the Logout dropdown item.
<a class="dropdown-item" href="{{ route('profile') }}">Profile</a>
Now if you click on the Profile link it will load the below view.
Configuring FileSystem for Storage
After finishing our view templates modification, now we need to configure our file system where we will be uploading images. Go to config/filesystem.php
file and change the settings for public
disk with below.
'public' => [ 'driver' => 'local', 'root' => public_path(), 'url' => env('APP_URL').'/public', 'visibility' => 'public', ],
Image Upload Trait
You can handle the image uploading logic within your controller, but I would like to separate this logic into a trait which we can use later on if we need to upload images.
In your app folder, create folder called Traits and add a php file called UploadTrait.php. Add below code snippet in it.
namespace App\Traits; use Illuminate\Support\Str; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; trait UploadTrait { public function uploadOne(UploadedFile $uploadedFile, $folder = null, $disk = 'public', $filename = null) { $name = !is_null($filename) ? $filename : Str::random(25); $file = $uploadedFile->storeAs($folder, $name.'.'.$uploadedFile->getClientOriginalExtension(), $disk); return $file; } }
In the above code example, we are creating a new function called uploadOne
which will handle the file uploading by taking the uploaded image, folder, disk, and filename parameters.
Firstly, we are checking if a filename has been passed, if not then we are creating a random string name.
Next we are uploading the file using UploadedFile‘s storeAs
method and returning the file we just stored. Nothing fancy.
Processing Image Upload in Profile Controller
After setting up the filesystem and creating a trait, it’s the time now to use the trait in our ProfileController for handling the form submission. As we already have created a route which will hit the updateProfile method. So let’s add that method. Use the below code example, and replace your current ProfileController with this one.
namespace App\Http\Controllers; use App\User; use Illuminate\Http\Request; use App\Traits\UploadTrait; class ProfileController extends Controller { use UploadTrait; public function __construct() { $this->middleware('auth'); } public function index() { return view('auth.profile'); } public function updateProfile(Request $request) { // Form validation $request->validate([ 'name' => 'required', 'profile_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048' ]); // Get current user $user = User::findOrFail(auth()->user()->id); // Set user name $user->name = $request->input('name'); // Check if a profile image has been uploaded if ($request->has('profile_image')) { // Get image file $image = $request->file('profile_image'); // Make a image name based on user name and current timestamp $name = Str::slug($request->input('name')).'_'.time(); // Define folder path $folder = '/uploads/images/'; // Make a file path where image will be stored [ folder path + file name + file extension] $filePath = $folder . $name. '.' . $image->getClientOriginalExtension(); // Upload image $this->uploadOne($image, $folder, 'public', $name); // Set user profile image path in database to filePath $user->profile_image = $filePath; } // Persist user record to database $user->save(); // Return user back and show a flash message return redirect()->back()->with(['status' => 'Profile updated successfully.']); } }
Above code is self-explained, we have injected our trait into this controller and added a updateProfile method.
updateProfile
method and read the comments to follow along. I have added enough comments to explain every single line.After updating the ProfileController, if you now go to the profile page and submit an image it should be working as expected. Try to upload a wrong file type and you will get the validation errors displayed as well like below.
Adding Profile Image to Dropdown Menu
By now you should have a fully functional image upload profile section. One last thing we need to show the currently uploaded image next to the username in header like in the demo image. For that in your app.blade.php
layout file, replace this:
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> {{ Auth::user()->name }} <span class="caret"></span> </a>
with this:
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> @if (auth()->user()->image) <img src="{{ asset(auth()->user()->image) }}" style="width: 40px; height: 40px; border-radius: 50%;"> @endif {{ Auth::user()->name }} <span class="caret"></span> </a>
Now if you upload an image again, you will be able to see the uploaded image before the user name.
Great! we have successfully created a profile update section with Laravel Image Upload. You can find the Source Code of the above example on Github.
If you have any question or suggestion to improve this post, please let me know in the comments box below.
How to delete the existing image after updating the image?
What if i just want delete the photo from server?
Hi,
You can create a deleteOne method in the trait with following code.
Change the
$disk
value to whatever you are using.How to retrive(featch) this uploaded file/images.
Hi,
Images are stored in the public folder in this post and a path to the image will be stored in the database table. Then you can call the image path like below.
Thanks
Hello there thanks for this awesome post. It really helped me with my project. But I also have another problem on my project about relationships that’s is showing images that belongs to a certain post. I just wanted to know if anyone can help me out with it if I posted it here. Thanks. Zeus.
Yes Sure.
Hello am new to laravel, though my question may sound stupid but please someone can still help out. I want to know if I can use the same steps as stated above for image upload to upload a zip file??
Yes you can use the same uploadOne() method to store any type of file upload.
I want to keep the image when validate?
Good for me
public function getImageAttribute(){
return $this->image;
}
This method makes an error
It supposes to be
profile_image
. That’s what I have used in the example.Thanks
how do i resize the image
Yo Ssup. Thanks for this. Before i was copying and pasting my upload code all over, and now with this i can easily reuse it because of the trait. 🙂 Now that i think about it its funny how i have been coding for a while but never thought of using traits.
Symfony\Component\Debug\Exception\FatalThrowableError
Call to undefined function App\Http\Controllers\str_slug()
error uploading image, cannot proceed
Change
str_slug()
withStr::slug();
and include the class like thisuse Illuminate\Support\Str;
.cool
Awesome dude thanks
how about if not local, i want to upload in my server that image. so how to set up?
You can use the FTP for uploading images to your own server.
hi ,i want to upload video or text ,word,…. ,what should I do? thanks
I’m working on an API, how do I call the Image from my frontend
hi,
it just awesome post but i wanna know a little about of that, will this work same if i am trying to upload image from a bootstrap modal in laravel.
Thanks a lot