Building a Simple CRUD Application in Laravel: A Practical Guide
Building a CRUD application is one of the best ways to learn the core pieces of Laravel. In this guide, we will create a simple Post resource that supports Create, Read, Update, and Delete operations using Eloquent, resource routes, validation, and Blade views.
1. Create the Laravel Project
Make sure Composer and a supported PHP version are installed, then run:
composer create-project --prefer-dist laravel/laravel laravel-crud
cd laravel-crud
php artisan serveThe development server is normally available at http://localhost:8000.
2. Configure the Database
Update .env for your database environment. For MySQL, for example:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_database_user
DB_PASSWORD=your_database_password
Use a dedicated database account with only the privileges the application requires.
3. Create the Model and Migration
Generate a Post model and migration:
php artisan make:model Post -mEdit the generated migration:
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}Run the migration:
php artisan migrate4. Create the CRUD Controller
Generate the controller:
php artisan make:controller PostControllerAdd the resource actions in app/Http/Controllers/PostController.php:
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->get();
return view('posts.index', compact('posts'));
}
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
Post::create($validated);
return redirect()->route('posts.index');
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
public function update(Request $request, Post $post)
{
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
$post->update($validated);
return redirect()->route('posts.index');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index');
}
}Using the validated array instead of $request->all() prevents unrelated request fields from being passed to Eloquent.
5. Configure the Post Model
Allow the intended fields to be mass assigned in app/Models/Post.php:
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'content'];
}6. Create Blade Views
Create a simple layout at resources/views/layouts/app.blade.php:
<html>
<head>
<title>CRUD App - @yield('title')</title>
</head>
<body>
<div class="container">
@yield('content')
</div>
</body>
</html>
An example resources/views/posts/index.blade.php:
@extends('layouts.app')
@section('content')
<h1>Posts</h1>
<a href="{{ route('posts.create') }}">Create New Post</a>
<ul>
@foreach($posts as $post)
<li>
<a href="{{ route('posts.show', $post) }}">{{ $post->title }}</a>
<a href="{{ route('posts.edit', $post) }}">Edit</a>
<form action="{{ route('posts.destroy', $post) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit">Delete</button>
</form>
</li>
@endforeach
</ul>
@endsection
Create similar create, edit, and show views with the appropriate form fields and actions. Keep @csrf on state-changing forms and use @method('PUT') or @method('PATCH') for updates.
7. Define Resource Routes
Add the resource route in routes/web.php:
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
Route::resource('posts', PostController::class);Laravel generates the standard index, create, store, show, edit, update, and destroy routes.
8. Test the Application
Open http://localhost:8000/posts and test creating, viewing, editing, and deleting posts. Also test validation failures and missing records so you understand how Laravel handles unsuccessful requests.
Conclusion
A small CRUD application introduces several Laravel fundamentals at once: migrations, Eloquent models, validation, route-model binding, resource controllers, Blade templates, and CSRF protection. From here, you can add pagination, authorization policies, form requests, relationships, tests, or a richer frontend as the application grows.