Laravel 12 makes it easy to build CRUD applications with file and image uploads using its powerful Eloquent ORM and built-in file storage system. In this tutorial, we’ll create a CRUD application where users can upload images along with their data.
By the end of this guide, you will learn:
✅ How to set up a Laravel 12 project
✅ How to create a model, migration, and controller
✅ How to upload and validate images
✅ How to perform CRUD operations (Create, Read, Update, Delete)
✅ How to display images in Blade templates
Let’s get started! 🚀
Make sure you have Composer installed. Then, create a new Laravel 12 project:
composer create-project laravel/laravel laravel12-crud
cd laravel12-crud
Run the Laravel development server:
php artisan serve
Configure your .env
file for database connection:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crud_db
DB_USERNAME=root
DB_PASSWORD=
Run the migration command to create the default tables:
php artisan migrate
Generate a model with a migration and controller for storing images:
php artisan make:model Post -mcr
Now, open the migration file inside database/migrations/
and update the up()
method:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description');
$table->string('image')->nullable();
$table->timestamps();
});
}
Run the migration:
php artisan migrate
Modify the Post.php
model file:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'description', 'image'];
}
web.php
Modify the routes/web.php
file:
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
PostController.php
Modify app/Http/Controllers/PostController.php
:
public function index()
{
$posts = Post::latest()->paginate(5);
return view('posts.index', compact('posts'));
}
Show Create Form
public function create()
{
return view('posts.create');
}
Store Post with Image
public function store(Request $request)
{
$request->validate([
'title' => 'required|max:255',
'description' => 'required',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048'
]);
$data = $request->all();
if ($request->hasFile('image')) {
$imageName = time() . '.' . $request->image->extension();
$request->image->move(public_path('uploads'), $imageName);
$data['image'] = $imageName;
}
Post::create($data);
return redirect()->route('posts.index')->with('success', 'Post created successfully!');
}
Show Edit Form
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
Update Post with Image
public function update(Request $request, Post $post)
{
$request->validate([
'title' => 'required|max:255',
'description' => 'required',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048'
]);
$data = $request->all();
if ($request->hasFile('image')) {
// Delete old image
if ($post->image) {
unlink(public_path('uploads/' . $post->image));
}
$imageName = time() . '.' . $request->image->extension();
$request->image->move(public_path('uploads'), $imageName);
$data['image'] = $imageName;
}
$post->update($data);
return redirect()->route('posts.index')->with('success', 'Post updated successfully!');
}
Delete Post
public function destroy(Post $post)
{
if ($post->image) {
unlink(public_path('uploads/' . $post->image));
}
$post->delete();
return redirect()->route('posts.index')->with('success', 'Post deleted successfully!');
}
resources/views/posts/create.blade.php
)<form action="{{ route('posts.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="text" name="title" placeholder="Title">
<textarea name="description" placeholder="Description"></textarea>
<input type="file" name="image">
<button type="submit">Submit</button>
</form>
resources/views/posts/index.blade.php
)@foreach ($posts as $post)
<h2>{{ $post->title }}</h2>
<p>{{ $post->description }}</p>
@if($post->image)
<img src="{{ asset('uploads/' . $post->image) }}" width="100">
@endif
<a href="{{ route('posts.edit', $post->id) }}">Edit</a>
<form action="{{ route('posts.destroy', $post->id) }}" method="POST">
@csrf @method('DELETE')
<button type="submit">Delete</button>
</form>
@endforeach
In this tutorial, we successfully built a Laravel 12 CRUD application with image upload. You learned:
✅ How to set up Laravel and connect a database
✅ How to create models, migrations, and controllers
✅ How to upload images and display them
✅ How to perform CRUD operations in Laravel
Now, you can extend this application by adding user authentication, API integration, or multiple file uploads. 🚀