Kritim Yantra
Feb 28, 2025
Welcome to this comprehensive guide on uploading images in Laravel 12! Whether you're building a blog, an e-commerce site, or a social media platform, handling image uploads is a common requirement. In this tutorial, I’ll walk you through the entire process—from setting up your Laravel project to displaying the uploaded images on your website. We’ll use simple language and detailed explanations to ensure you understand each step.
By the end of this guide, you’ll be able to:
composer create-project laravel/laravel your-project-name "12.*"
.env
file. Laravel 12 supports MySQL, PostgreSQL, SQLite, and more.If you’re new to Laravel, don’t worry—I’ll explain everything as we go along.
To store information about the uploaded images, we need a model and a corresponding database table. Let’s create an Image
model and a migration to define the table structure.
Run this command in your terminal:
php artisan make:model Image -m
This generates two files:
app/Models/Image.php
: The model file.database/migrations/xxxx_xx_xx_create_images_table.php
: The migration file (the timestamp will vary).Open the migration file and update the up
method to define the table columns:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateImagesTable extends Migration
{
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('path'); // To store the image file path
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('images');
}
}
This creates an images
table with:
id
column for unique identification.path
column to store the file path of the uploaded image.created_at
and updated_at
) to track when records are added or modified.Run the migration to create the table in your database:
php artisan migrate
Next, we need a controller to handle the logic for uploading and displaying images. Create an ImageController
with this command:
php artisan make:controller ImageController
This creates a file at app/Http/Controllers/ImageController.php
. Open it and add two methods:
index
: To display the upload form and list of uploaded images.upload
: To handle the image upload process.Here’s the initial structure:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Image;
class ImageController extends Controller
{
public function index()
{
// Logic to display images
}
public function upload(Request $request)
{
// Logic to handle image upload
}
}
We’ll fill in these methods later.
Routes tell Laravel how to handle incoming requests. We need two routes:
Open routes/web.php
and add these routes:
use App\Http\Controllers\ImageController;
Route::get('/images', [ImageController::class, 'index'])->name('images.index');
Route::post('/images', [ImageController::class, 'upload'])->name('images.upload');
These routes:
GET /images
to the index
method for displaying the form and images.POST /images
to the upload
method for processing the upload.Now, let’s create a Blade template for the upload form. Blade is Laravel’s templating engine, allowing us to mix HTML with dynamic content.
Create a new file at resources/views/images/index.blade.php
and add this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Upload</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1>Upload an Image</h1>
@if(session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<form action="{{ route('images.upload') }}" method="POST" enctype="multipart/form-data" class="mb-5">
@csrf
<div class="form-group">
<label for="image">Select Image</label>
<input type="file" name="image" id="image" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary mt-2">Upload</button>
</form>
<h2>Uploaded Images</h2>
<div class="row">
<!-- Images will be displayed here -->
</div>
</div>
</body>
</html>
Key points:
enctype="multipart/form-data"
, which is essential for file uploads.@csrf
adds a CSRF token for security.
Let’s implement the upload
method in ImageController
to process the uploaded image. Update it like this:
use Illuminate\Http\Request;
use App\Models\Image;
use Illuminate\Support\Facades\Storage;
public function upload(Request $request)
{
// Validate the uploaded file
$request->validate([
'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048', // Max 2MB
]);
// Store the image in the 'public' disk
$path = $request->file('image')->store('images', 'public');
// Save the image path to the database
$image = new Image();
$image->path = $path;
$image->save();
// Redirect back with a success message
return redirect()->route('images.index')->with('success', 'Image uploaded successfully!');
}
This code does the following:
storage/app/public/images
using the public disk.images
table./images
page with a success message.
Now, update the index
method to retrieve and display the uploaded images:
public function index()
{
$images = Image::latest()->get();
return view('images.index', compact('images'));
}
This fetches all images from the database (newest first) and passes them to the index.blade.php
view.
Next, update the Blade template to display the images. Add this inside the <div class="row">
element:
@foreach($images as $image)
<div class="col-md-4 mb-3">
<img src="{{ asset('storage/' . $image->path) }}" alt="Uploaded Image" class="img-fluid">
</div>
@endforeach
This loop displays the images in a responsive grid. The asset
helper generates the correct URL for each image.
To make uploaded images accessible via the browser, create a symbolic link from public/storage
to storage/app/public
. Run this command:
php artisan storage:link
This allows files in storage/app/public
to be accessed publicly (e.g., at /storage/images/your-image.jpg
).
Let’s test everything:
php artisan serve
http://localhost:8000/images
in your browser.If something doesn’t work, ensure that:
storage:link
command ran successfully.Congratulations! You’ve built a complete image upload system in Laravel 12. You learned how to set up a model and migration, create a controller and routes, design an upload form, handle file storage, and display images on your site.
This is a solid starting point—you can expand it further by adding features like image deletion, editing, or linking images to other models (e.g., users or products). If you have questions or run into issues, feel free to leave a comment. Happy coding with Laravel!
No comments yet. Be the first to comment!
Please log in to post a comment:
Continue with Google