Application development often requires to upload multiple images at the same time. This feature is supported by Laravel applications. In the previous tutorials, we discussed how to upload single image in Laravel. So, let us now look at a step by step example to upload multiple images in Laravel.
Step 1: Install and Create new Project.
Firstly, we will install Laravel 9 and create a new project. We will have a simple form with a file input field. You can use it to select multiple images. Prior to submitting the form we will store those images in a folder and database.
composer create-project laravel/laravel upload_multiple_images
Step 2: Create new Migrations
Secondly, to store multiple images and their paths in a single place, we will need a separate table to handle it. Therefore, we will create migrations for a new images table.
php artisan make:migration create_new_images_table
The resulting migrations file will look as shown below.
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('images');
}
};
The details above have the up() function to create a new table ‘images’ with the three fields specified in the create function. The down() function drops the ‘images’ table, if it exists in database. After adding the details as above, we will run the migrations.
php artisan migrate
Step 3: Create new Modal
Next step, we create an Images Modal.
php artisan make:model Images
The Modal will come under the app/Models directory and has the code as shown below.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Images extends Model
{
use HasFactory;
protected $fillable = [
'name'
];
}
Step 4: Create new Routes
New routes in the routes/web.php file are created to link the Controller functions and blade views.
Route::controller(ImagesController::class)->group(function(){
Route::get('images-upload', 'index');
Route::post('images-upload', 'save')->name('images.store');
});
Step 5: Create new Controller
Now we create a controller that handles retrieving of images and uploading to the database.
php artisan make:controller ImagesController
We will then populate the Controller file with the code as shown below.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Image;
class ImagesController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('imagesUpload');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function save(Request $request)
{
$request->validate([
'images' => 'required',
'images.*' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$images = [];
if ($request->images){
foreach($request->images as $key => $image)
{
$imageName = time().rand(1,99).'.'.$image->extension();
$image->move(public_path('images'), $imageName);
$images[]['name'] = $imageName;
}
}
foreach ($images as $key => $image) {
Image::create($image);
}
return back()
->with('success','You have successfully upload image.')
->with('images', $images);
}
}
The index() function returns the view where a user can upload images. Image data from the view is processed in the save function. After validation, the image array processes the multiple images using a foreach loop. Therefore, each image is moved to the images location. For example, this can be the public path or an image storage folder. Locations of both paths are stated in upload single image tutorial. Consequently, a success message is returned if all steps go smoothly.
Step 6: Create new Blade file
Finally, the last step will be to create a blade file. This will make a user view the multi-image select and upload option.
<!DOCTYPE html>
<html>
<head>
<title>Laravel 9 Upload Multiple Images Example - scratchcoding.dev</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Laravel 9 Upload Multiple Images Example - scratchcoding.dev</h2>
</div>
<div class="panel-body">
@if ($message = Session::get('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>{{ $message }}</strong>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@foreach(Session::get('images') as $image)
<img src="images/{{ $image['name'] }}" width="300px">
@endforeach
@endif
<form action="{{ route('images.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label class="form-label" for="inputImage">Select Images:</label>
<input
type="file"
name="images[]"
id="inputImage"
multiple
class="form-control @error('images') is-invalid @enderror">
@error('images')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<button type="submit" class="btn btn-success">Upload</button>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
The blade file above views the upload images option to the user. In addition, it has two separate divs that pop up required messages. One for success and one for error. The error directive will display any error messages.