How to Build a Laravel 12 CRUD Application with Livewire

How to Build a Laravel 12 CRUD Application with Livewire

How to Build a Laravel 12 CRUD Application with Livewire

Introduction

In this tutorial, you’ll learn how to build a complete CRUD (Create, Read, Update, Delete) application in Laravel 12 using Livewire — a full-stack framework that makes building modern, reactive web apps simple and elegant without leaving the comfort of Laravel.

Requirements

  • PHP >= 8.1

  • Composer

  • Laravel 12

  • Node.js & npm (optional for styling)

  • Basic Laravel knowledge

Step 1: Create a New Laravel Project

composer create-project laravel/laravel laravel12-livewire-crud

Step 2: Install Livewire

Install Livewire using Composer:

composer require livewire/livewire 

Step 3: Include Livewire Assets

Edit your layout file at resources/views/layouts/app.blade.php:

<!DOCTYPE html> <html> <head> <title>Laravel Livewire CRUD</title> @livewireStyles </head> <body> <div class="container mt-4"> {{ $slot }} </div> @livewireScripts </body> </html>

Step 4: Create Post Model and Migration

php artisan make:model Post -m

Edit the migration file:

// database/migrations/xxxx_xx_xx_create_posts_table.php public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('body'); $table->timestamps(); }); }

Step 5: Configure Database

In your .env file:

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=db_crud DB_USERNAME=root DB_PASSWORD=

Then run the migration:

php artisan migrate

Step 6: Create Livewire Component

php artisan make:livewire PostCrud

Step 7: Open Your Post Model

File: app/Models/Post.php

Add the $fillable property like this:

namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $fillable = ['title', 'body']; }

Step 8: Add Livewire Component Logic

Edit app/Livewire/PostCrud.php:

namespace App\Livewire; use App\Models\Post; use Livewire\Component; class PostCrud extends Component { public $posts, $title, $body, $post_id; public $isEdit = false; protected $rules = [ 'title' => 'required|string|max:255', 'body' => 'required|string', ]; public function render() { $this->posts = Post::latest()->get(); return view('livewire.post-crud')->layout('layouts.app'); } public function resetInput() { $this->title = ''; $this->body = ''; $this->post_id = null; $this->isEdit = false; } public function store() { $this->validate(); Post::create([ 'title' => $this->title, 'body' => $this->body, ]); session()->flash('message', 'Post created successfully.'); $this->resetInput(); } public function edit($id) { $post = Post::findOrFail($id); $this->post_id = $post->id; $this->title = $post->title; $this->body = $post->body; $this->isEdit = true; } public function update() { $this->validate(); if ($this->post_id) { $post = Post::find($this->post_id); $post->update([ 'title' => $this->title, 'body' => $this->body, ]); session()->flash('message', 'Post updated successfully.'); $this->resetInput(); } } public function delete($id) { Post::find($id)->delete(); session()->flash('message', 'Post deleted successfully.'); } }

Step 9: Create the View

Create the file:
resources/views/livewire/post-crud.blade.php

<div> <h2>Livewire CRUD Example</h2> @if (session()->has('message')) <div style="color: green;">{{ session('message') }}</div> @endif <form wire:submit.prevent="{{ $isEdit ? 'update' : 'store' }}"> <input type="text" wire:model="title" placeholder="Title"><br> @error('title') <span style="color:red;">{{ $message }}</span><br> @enderror <textarea wire:model="body" placeholder="Body"></textarea><br> @error('body') <span style="color:red;">{{ $message }}</span><br> @enderror <button type="submit">{{ $isEdit ? 'Update' : 'Save' }}</button> @if($isEdit) <button type="button" wire:click="resetInput">Cancel</button> @endif </form> <hr> <table border="1" cellpadding="5"> <tr> <th>ID</th><th>Title</th><th>Body</th><th>Actions</th> </tr> @foreach($posts as $post) <tr> <td>{{ $post->id }}</td> <td>{{ $post->title }}</td> <td>{{ $post->body }}</td> <td> <button wire:click="edit({{ $post->id }})">Edit</button> <button wire:click="delete({{ $post->id }})">Delete</button> </td> </tr> @endforeach </table> </div>

Step 10: Add Route

Update routes/web.php:

use App\Livewire\PostCrud; Route::get('/', PostCrud::class);

Step 11: Run the App

php artisan serve

Open your browser at:
👉 http://localhost:8000

You should see the Livewire CRUD interface!

Optional Enhancements

  • Style with Bootstrap/Tailwind CSS

  • Add pagination using WithPagination Livewire trait

  • Use modals for editing/creating

  • Add search and filters

Conclusion

You now have a fully functional Laravel 12 CRUD application powered by Livewire. This approach makes it easy to build dynamic UIs without writing any custom JavaScript.

Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
close