In this small project, we will install and configure Laravel 11 with Bootstrap and jQuery. Then, we will create a form that can be populated and try to upload multiple images in a single go and save the names in the database.
Here is the step-by-step guide:
Step 1: Install and configure Laravel 11
composer create-project laravel/laravel multipleimages --prefer-dist
Go inside the folder and install the laravel/ui package:
composer require laravel/ui
Now, add the Bootstrap library using laravel/ui:
php artisan ui bootstrap
Run these commands step by step to your project terminal.
npm install npm run dev
Go to the Laravel project root and start the development server using this command:
php artisan serve
Head to the browser and go to this link: https://localhost:8000
This is how Laravel 11 looks like this:
Step 2: Connecting Laravel with Database
Go to the .env file and add the database credentials.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=8889 DB_DATABASE=multipleimages DB_USERNAME=root DB_PASSWORD=root
In the next step, create an “Image” model and migration file.
php artisan make:model Image -m
It will create an Image.php model and migration file inside the database >> migrations >> create_images_table.php file.
Add the below code inside the up() function of the create_images_table.php file.
<?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::create('images', function (Blueprint $table) { $table->id(); $table->string('filename'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('images'); } };
Now, create a table based on the above migration:
php artisan migrate
It will create a “images” table in the database.
We need to set up the controller for our application.
Type the following command to generate a controller.
php artisan make:controller ImageController
It will generate an ImageController.php file inside the App >> Http >> Controllers directory.
Step 3: Define routes in the web.php file.
Go to the routes >> web.php file, import the ImageController.php file at the head, and add two routes:
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\ImageController; Route::get('images/upload', [ImageController::class, 'create'])->name("uploads.create"); Route::post('images/upload', [ImageController::class, 'store'])->name("uploads.store");
The “get” route displays the form, and the “post” route stores image details in the database and uploads them to the server.
In the ImageController, import the Image.php model and add the create() function with the below code.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Image; class ImageController extends Controller { public function create() { return view('create'); } public function store(Request $request) { } }
We will write the code for the store() function later!
Step 4: Create views
Let’s create a master view called layout.blade.php file inside the views folder.
<!DOCTYPE html> <html lang="en"> <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"> <title>Laravel Multiple Images Upload</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script> </head> <body> <div class="container"> @yield('content') </div> <!-- Scripts --> @vite(['resources/sass/app.scss', 'resources/js/app.js']) </body> </html>
We used the @vite directive to import CSS and JS assets into our project. We included jQuery separately!
Create a create.blade.php file inside the views folder and write the below code.
@extends('layout') @section('content') <h3>Laravel Multiple Images Upload</h3> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @if(session('success')) <div class="alert alert-success"> {{ session('success') }} </div> @endif <form method="post" action="{{ route('uploads.store') }}" enctype="multipart/form-data"> @csrf <div class="input-group control-group increment" > <input type="file" name="filename[]" class="form-control"> <div class="input-group-btn"> <button class="btn btn-success" type="button"><i class="glyphicon glyphicon-plus"></i>Add</button> </div> </div> <div class="clone hide"> <div class="control-group input-group" style="margin-top:10px"> <input type="file" name="filename[]" class="form-control"> <div class="input-group-btn"> <button class="btn btn-danger" type="button"><i class="glyphicon glyphicon-remove"></i> Remove</button> </div> </div> </div> <button type="submit" class="btn btn-primary" style="margin-top:10px"> Upload </button> </form> </div> @endsection
We are extending the master layout from the layout.blade.php file.
We added a simple web form to add multiple images. The form looks like this:
However, we need functionality to populate the input field when we click the add button. So first, let us do that.
We will use the jQuery for that feature.
Step 5: Adding the jQuery code to populate the input field
Write the jQuery code to populate the form field inside the create.blade.php file.
@extends('layout') @section('content') <h3>Laravel Multiple Images Upload</h3> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @if(session('success')) <div class="alert alert-success"> {{ session('success') }} </div> @endif <form method="post" action="{{ route('uploads.store') }}" enctype="multipart/form-data"> @csrf <div class="input-group control-group increment" > <input type="file" name="filename[]" class="form-control"> <div class="input-group-btn"> <button class="btn btn-success" type="button"><i class="glyphicon glyphicon-plus"></i>Add</button> </div> </div> <div class="clone hide"> <div class="control-group input-group" style="margin-top:10px"> <input type="file" name="filename[]" class="form-control"> <div class="input-group-btn"> <button class="btn btn-danger" type="button"><i class="glyphicon glyphicon-remove"></i> Remove</button> </div> </div> </div> <button type="submit" class="btn btn-primary" style="margin-top:10px"> Upload </button> </form> </div> <script type="text/javascript"> $(document).ready(function() { // When the 'Add' button (btn-success) is clicked $(".btn-success").click(function() { var clone = $(".clone").clone(true).removeClass('clone hide'); // Clone the hidden template element and remove 'clone' and 'hide' classes $(".increment").after(clone); // Insert the cloned element after the element with class 'increment' }); // When the 'Remove' button (btn-danger) is clicked $("body").on("click", ".btn-danger", function() { $(this).closest(".control-group").remove(); // Remove the closest parent with class 'control-group' }); }); </script> @endsection
If you save this file and go to this URL: http://localhost:8000/images/upload, you can populate the fields like this:
Step 6: Add Laravel Image validation.
We are inserting multiple images, so we need to create an array validation in our project.
Add the following code to validate our input file in an ImageController.php file.
public function store(Request $request) { $request->validate([ 'filename' => 'required', 'filename.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048' ]); }
This code checks against the required field and the image type.
If the input file does not contain an image or jpg, png, gif, or svg, it throws an error, and laravel catches it and displays these errors in the front end.
We already wrote a code to display the errors, so let’s head to a web form and try to submit the data without any image and see the error:
Let’s try uploading a PDF file to see if it validates the request. Here is the output:
Step 7: Uploading images and save their details to the database
After checking the validation, we must store the image names in our database.
Let’s write our final code to upload the images to the server and save the details in the database inside the ImageController’s store() function.
public function store(Request $request) { $request->validate([ 'filename' => 'required', 'filename.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048' ]); if ($request->hasfile('filename')) { foreach ($request->file('filename') as $image) { $name = $image->getClientOriginalName(); $image->move(public_path() . '/images/', $name); $data[] = $name; } } $image = new Image(); $image->filename = json_encode($data); $image->save(); return back()->with('success', 'Your images has been successfully'); }
In this code, we are checking if the request has file input. Since the input is multiple images, we are iterating a loop to get the file’s original name, upload it to the public path of the server, and save the image details in the database in json format.
Let’s upload three images:
Now, when I upload the images, I get the output like this:
Let’s check the database and see if it saved the details:
Now, let’s check out the public >> images folder and see if uploaded images exist!
That’s it, fellow coders!
Krunal Lathiya is a seasoned Computer Science expert with over eight years in the tech industry. He boasts deep knowledge in Data Science and Machine Learning. Versed in Python, JavaScript, PHP, R, and Golang. Skilled in frameworks like Angular and React and platforms such as Node.js. His expertise spans both front-end and back-end development. His proficiency in the Python language stands as a testament to his versatility and commitment to the craft.
You forgot to add use App\Form; in FormController.
In case someone stumbles up here and is stuck
Perfect i was looking for this tutorials, everybody does it only for one image. Thanks mate.
Thanks for the post it’s very helpfull if possible provide the Demo option here.
So after seeing the Demo we can save or time to it’s meeting or requirment or not.
Hi mate. Thanks for this great tutorial.
Kindly, could you explain how one can retrieve the images? Thanks
Hello, Why is it saving only one image in the database?
Regards
Nope, I guess you are having a mistake. It actually saves multiple images in the database as well as uploads on the server.
thats true Krunal, but I think I have an observation, I’m new to this, but I think that when you add an image the js you use has some error because they do not add the names of the images as it should, nor less able to select more than one and list the images that were selected. Could you help me to fixed?
how to retrieve the data of json encode?
for example i want to display the every image what should i do? i have tried json_decode but its not working properly on index method.
I have the same issue why is it saving only one image in the database? i use laravel 5.6 do you think is the problem ? thanks a lot.
Dominic
It is saving multiple images, but it is stored in a json format. Check your database.
please i have been stuck on this for a very long time, please could u tell me how to display this images in my view
You have to use jQuery plugins like this one
how to use that?
You can fetch the images from your public folder and iterate using forEach function and display image one by one!
Thanks !
but why when i’ve been uploaded 3 images, it’s only save one filename/json in the Database, but in public folder it’s work, they save all the 3 images ?
Yes, the image names will be saved in json format and your 3 images will be saved on public >> images folder in your Laravel application!
Below are some corrections i did , if anyone want files to be saved with different id , instead of array also added time() in $name so it will stop messing with different images with same name.
// Controller
public function store(Request $request)
{
$this->validate($request, [
‘filename’ => ‘required’,
‘filename.*’ => ‘image|mimes:jpeg,png,jpg,gif,svg|max:2048’
]);
if($request->hasfile(‘filename’))
{
foreach($request->file(‘filename’) as $image)
{
$form= new Form();
$name=time().’.’.$image->getClientOriginalName();
$image->move(public_path().’/images/’, $name);
$data = $name;
$form->filename=$data;
$form->save();
}
}
return back()->with(‘success’, ‘Your images has been successfully’);
}
Thanks! That would be helpful for other users!
Thank you for your tutorial.it very much useful to me.
Thanks Antony! Keep learning and sharing!
Your tutorials are the best!!,
how can i display those pictures ..anyone to help
Thanks Subsin! Keep learning and sharing!
You can as well use : in case you dont want to add the jquery
how to solve error Call to a member function getClientOriginalName() on a non-object
That means your input request is empty! There must be some problem with your HTML form.
Please tell me how to display this images
how to display this images?
I use json_decode to display path but not working ?!
@foreach (json_decode($product->product_image, true) as $image)
@endforeach
please help in knowing how to display those images I am stuck
To display those images, you need to fetch the image from public path and display on the frontend!
again and again it showing image field is reuired
?can anyone help me
Add
Remove
Add
Remove
public function store(Request $request)
{
$request->validate([
‘service_center’ => ‘required’,
‘outcome’ => ‘required’,
‘cbdm_images’ => ‘required|image|mimes:jpeg,png,jpg,svg|max:2048’,
‘cbdm_file’ => ‘required|mimes:pdf,doc,excel’,
]);
$cbdm_info = new Cbdm_details([
$cbdm_info->service_center =$request->get(‘service_center’),
$cbdm_info->outcome = $request->get(‘outcome’),
$cbdm_info->cbdm_images = $request->file(‘cbdm_images’),
$cbdm_info->cbdm_file = $request->file(‘cbdm_file’)
]);
if($file = $request->file(‘cbdm_images’)) {
$name = time() . $file->getClientOriginalName();
$file->move(‘/cbdm-img-file’, $name);
$photo = Cbdm_details::create([‘file’=>$name]);
$input[‘cbdm_images’] = $photo->id;
dd($file);
}
$cbdm_info->save();
return redirect(‘admin/cbdm’)->with(‘success’, ‘Successfully Added CBDM Details!’);
Maybe you need to print your request object and see if every field is there! Try print_r() function and exit to stop the execution and print your request object.
In array only first file data is storing , what the issues please let me know its urgent
Add
Remove
‘cbdm_images.*’ => ‘image|mimes:jpeg,png,jpg,gif,svg|max:2048′,
//’cbdm_file’ => ‘mimes:pdf,doc,.xlsx’
]);
if($request->hasFile(‘cbdm_images’)){
foreach($request->file(‘cbdm_images’) as $image){
$filenameWithExt = $image->getClientOriginalName();
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
$extension = $image->getClientOriginalExtension();
$fileNameToStore = $filename.’_’.time().’.’.$extension;
$path = $image->storeAs(‘cbdm’,$fileNameToStore);
$data[] = $fileNameToStore;
dd($data);
}
}
$cbdm_info->cbdm_images = json_encode($data);
$cbdm_info->save();
nice. would be good to see how this saves in the dbase. does it create a row for each image with an id or does it save all the filenames in an array in 1 row?
Right now, I am just storing image names as json format!
$name=$image->getClientOriginalName();
$image->move(public_path().’/properties/’, $name);
$url= URL::to(‘/’) . ‘/properties/’ . $image->getClientOriginalName();
$data[] = $url;
Am storing the image location url to my database column call images.
and the are in this form…
[“http:\/\/kizflex.local\/properties\/10.jpg”,”http:\/\/kizflex.local\/properties\/11.jpg”]
So how can iterate through this particular column so as to get each address and display it in my view?
Hello, in what way could I show the images stored in a view?
and tried:
product-> image [0]
product-> image [1]
Without any result
excuse me sir, i have a question,
is possible to add some text field like a title image and the value automatically generate by file name?
if possible, can you help me?
Yes, that’s possible!