How To Upload Multiple Image In Laravel 10 step by step tutorial | Complete CRUD with Multiple File Upload Tutorial Laravel
In this post, you will learn how to upload multiple images in Laravel 10 step by step.
We will take an example of "Product" and "Product Images" for this tutorial which is uploading multiple images in Laravel 10.
We will cover 1. upload "multiple images" for each "product". 2. Display the uploaded images, 3. Delete each image on click. So Let's get started.
I have used Bootstrap 5 classes the Design the UI / UX.
Step 1: Create a Laravel Project and Connect with your database
Step 2: Create a Completed CRUD Operation for the Product. Learn: https://www.fundaofwebit.com/post/laravel-10-crud-application-example-tutorial
Step 3: Create a Migration for Product Images using the artisan command below:
php artisan make:migration create_product_images_table
after successfully creating the migration for "product images", paste the below code:
<?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('product_images', function (Blueprint $table) {
$table->id();
$table->foreignId('product_id');
$table->string('image');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('product_images');
}
};
Now let's migrate into the database using the artisan command given below:
php artisan migrate
Step 4: Create a Model for "Product" and "ProductImage"
Now create the "Product" Model using the artisan command below. If already created please ignore it.
php artisan make:model Product
after successfully creating Product Eloquent Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\
Model;
class Product extends Model
{
use HasFactory;
protected $table = "products";
protected $fillable = [
'name',
'slug',
'price',
'description',
];
}
Now create the "ProductImage" Model using the artisan command below.
php artisan make:model ProductImage
After successfully create the "ProductImage" model, paste the below code:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProductImage extends Model
{
use HasFactory;
protected $table = 'product_images';
protected $fillable = [
'product_id',
'image'
];
}
Step 5: Create a Route
This Route is created as upload images for each product. so only we are passing the {productId} in the below routes:
Route::get('products/{productId}/upload', [App\Http\Controllers\ProductImageController::class, 'index']);
Route::post('products/{productId}/upload', [App\Http\Controllers\ProductImageController::class, 'store']);
Route::get('product-image/{productImageId}/delete', [App\Http\Controllers\ProductImageController::class, 'destroy']);
Step 6: Create a Controller named "ProductImageController.php" using the artisan command given below:
php artisan make:controller ProductImageController
after successfully creating the Controller, lets paste the code:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use App\Models\ProductImage;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
class ProductImageController extends Controller
{
public function index(int $productId)
{
$product = Product::findOrFail($productId);
$productImages = ProductImage::where('product_id',$productId)->get();
return view('product-image.index', compact('product','productImages'));
}
public function store(Request $request, int $productId)
{
$request->validate([
'images.*' => 'required|image|mimes:png,jpg,jpeg,webp'
]);
$product = Product::findOrFail($productId);
$imageData = [];
if($files = $request->file('images')){
foreach($files as $key => $file){
$extension = $file->getClientOriginalExtension();
$filename = $key.'-'.time(). '.' .$extension;
$path = "uploads/products/";
$file->move($path, $filename);
$imageData[] = [
'product_id' => $product->id,
'image' => $path.$filename,
];
}
}
ProductImage::insert($imageData);
return redirect()->back()->with('status', 'Uploaded Successfully');
}
public function destroy(int $productImageId)
{
$productImage = ProductImage::findOrFail($productImageId);
if(File::exists($productImage->image)){
File::delete($productImage->image);
}
$productImage->delete();
return redirect()->back()->with('status', 'Image Deleted');
}
}
Step 7: Create a Blade file for product image upload as follows
Now let's create a folder named "product-image" in the following path: resources/ views/ product-images/ and then create a file named index.blade.php in that folder. The complete path: resources/ views/ product-image/ index.blade.php and paste the below code: (Note: Make sure the Extend your layout)
<div class="container mt-5">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h4>Upload Product Images
<a href="{{ url('products') }}" class="btn btn-primary float-end">Back</a>
</h4>
</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success">{{session('status')}}</div>
@endif
<h5>Product Name: {{ $product->name }}</h5>
<hr>
@if ($errors->any())
<ul class="alert alert-warning">
@foreach ($errors->all() as $error)
<li>{{$error}}</li>
@endforeach
</ul>
@endif
<form action="{{ url('products/'.$product->id.'/upload') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label>Upload Images (Max:20 images only)</label>
<input type="file" name="images[]" multiple class="form-control" />
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-12 mt-4">
@foreach ($productImages as $prodImg)
<img src="{{ asset($prodImg->image) }}" class="border p-2 m-3" style="width: 100px; height: 100px;" alt="Img" />
<a href="{{ url('product-image/'.$prodImg->id.'/delete') }}" >Delete</a>
@endforeach
</div>
</div>
</div>
Step 8: Add the "a tag" link in your "products foreach looped list" so we can upload image for each product, as shown below:
<a href="{{ url('products/'.$item->id.'/upload') }}" class="btn btn-info">Add / View Images</a>
So once you click on the Link, It will open the Step 7 FORM and from there you can upload multiple images and Display Multiple images and also delete each image.
It looks completely something like this as given below
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>Images</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach ($products as $item)
<tr>
<td>{{$item->id}}</td>
<td>{{$item->name}}</td>
<td>{{$item->description}}</td>
<td>
<a href="{{ url('products/'.$item->id.'/upload') }}" class="btn btn-info">Add / View Images</a>
</td>
<td>
// Your edit & delete button comes here.
</td>
</tr>
@endforeach
</tbody>
</table>
That's it. now let's serve the application using the artisan command:
php artisan serve
I hope it helps you. Thanks for reading.