Create Laravel CRUD Application
A completed guide for building CRUD application using Laravel, Tailwind CSS

This new article would like to share how I built a CRUD
application. After you
practice with this article, you will be able to create an application which can perform
operation CRUD (Create, Read, Update, and Delete)
using Laravel
.
What we cover in this articles
We use Laravel, Livewire, Tailwind CSS, Laravel Breeze(Starter Kits for Authentication) and below is our content which we will cover is this article.
- Setup Laravel project
- Configure database
- Install Laravel Breeze
- Install Livewire
- Implement CRUD operations
- Running the application
Setup Laravel project
To install a fresh Laravel 9 application
composer create-project laravel/laravel laravel-crud
where laravel-crud
is your project name.
Configure database connection
Now you have to configure the database variable in .env
to connect your laravel application with the database server.
DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=database_name // your database nameDB_USERNAME=database_user_name // your database userDB_PASSWORD=database_password // your datbase password
Install Laravel Breeze && Livewire
To make things more manageable, we use Laravel Breeze, a starter kit for authentication with Tailwind CSS 3. So we don't need to install and configure Tailwind.
- To Install Laravel Breeze via composer
composer require laravel/breeze
- To Setup breeze ui and auth scaffolding
php artisan breeze:install
- To Install dependencies
npm install && npm run dev
- To migrate
php artisan mgirate
- Install Livewire
composer require livewire/livewire
To activate Livewire on a page, we need to add @livewireStyles
and @livewireScripts
every page you want to use it.
Now let add it to our resources/views/layouts/app.blade.php
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Livewire CRUD') }}</title> <!-- Fonts --> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"> <!-- Styles --> <link rel="stylesheet" href="{{ asset('css/app.css') }}"> <!-- Scripts --> <script src="{{ asset('js/app.js') }}" defer></script> <!-- Add Livewire Style --> @livewireStyles </head> <body class="font-sans antialiased"> <div class="min-h-screen bg-gray-100"> @include('layouts.navigation') <!-- Page Heading --> <header class="bg-white shadow"> <div class="px-4 py-6 mx-auto max-w-7xl sm:px-6 lg:px-8"> {{ $header }} </div> </header> <!-- Page Content --> <main> {{ $slot }} </main> </div> <!-- Add Livewire Script --> @livewireScripts </body></html>
Implement CRUD Operations
- Create
Post
Model and Migrations
php artisan make:model Post -m
After running the command above, you will get a migration. We add field title
, description
.
<?php use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; class CreatePostsTable extends Migration{ /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('description'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); }}
You also generate a Model file in App/Models/Post.php
as below.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model; class Post extends Model{ use HasFactory; protected $fillable = [ 'title', 'description' ];}
Now you can hit a command php artisan migrate
to migrate your database schema
- Now let's create controller
php artisan make:controller PostController
and update our controller with code below.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class PostController extends Controller{ /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { return view('post'); }}
Create route for Post by edit routes/web.php
and add code below.
Route::get('post', [PostController::class,'index'])->name('post.index');
- Creating a Livewire Component To create a livewire component, run the following command:
php artisan make:livewire Post
This will create a new Post.php
class file and place it in the App\Views\Components
folder. Then, a corresponding
view
template is created and placed in resources/views/components
. To display the component, you can then use this Blade
syntax: <x-post/>
.
You can further explore Laravel Blade components in the documentation.
Now Let's create template file for post
in resources/views/post.blade.php
and add content as below.
<x-app-layout> <x-slot name="header"> <h2 class="text-xl font-semibold leading-tight text-gray-800"> Post </h2> </x-slot> <div class="py-12"> <div class="mx-auto max-w-7xl sm:px-6 lg:px-8"> <div class="overflow-hidden bg-white shadow-sm sm:rounded-lg"> <div class="p-6 bg-white border-b border-gray-200"> <livewire:post /> </div> </div> </div> </div></x-app-layout>
Next, You need to update the Post
component in app/Http/Livewire/Post.php
with code below.
<?php namespace App\Http\Livewire; use App\Models\Post;use Livewire\Component;use Livewire\WithPagination; class PostForm extends Component{ use WithPagination; public $title; public $description; public $post_id; protected $rules = [ 'title' => 'required', 'description' => 'required', ]; public function storePost() { $this->validate(); $post = Post::create([ 'title' => $this->title, 'description' => $this->description ]); $this->reset(); } public function edit($id) { $post = Post::find($id); $this->post_id = $post->id; $this->title = $post->title; $this->description = $post->description; } public function update() { $post = Post::updateOrCreate( [ 'id' => $this->post_id, ], [ 'title' => $this->title, 'description' => $this->description ], ); $this->reset(); } public function destroy($id) { Post::destroy($id); } public function render() { return view('livewire.post', ['posts' => Post::latest()->paginate(10)]); }}
Now you need to update livewire view component in resources/views/livewire/post.blade.php
<div> <h4 class="mb-4 text-2xl font-bold">Post </h4> <div> <div class="container mx-auto"> <form method="POST" wire:submit.prevent="storePost"> @csrf <div> <label for="title">Title</label> <input type="text" wire:model.lazy="title" class="w-full py-2 rounded"> @error('title') <span class="text-red-600">{{ $message }}</span> @enderror </div> <div class="mt-8"> <label class="block mb-2 text-xl">Description </label> <textarea wire:model.lazy="description" rows="3" cols="20" class="w-full rounded"> </textarea> @error('description') <span class="text-red-600">{{ $message }}</span> @enderror </div> <button type="submit" class="px-4 py-2 mt-4 text-white bg-blue-600 rounded"> Submit </button> <button type="submit" wire:click="update" class="px-4 py-2 text-white bg-indigo-600 rounded"> Update </button> </form> </div> <div class="flex flex-col mt-8"> <div class="py-2"> <div class="min-w-full border-b border-gray-200 shadow"> <table class="min-w-full"> <thead> <tr> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Id </th> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Title </th> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Edit </th> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Delete </th> </tr> </thead> <tbody class="bg-white"> @foreach($posts as $post) <tr> <td class="px-6 py-4 border-b border-gray-200"> <div class="flex items-center"> <div class="ml-4"> <div class="text-sm text-gray-900"> {{ $post->id }} </div> </div> </div> </td> <td class="px-6 py-4 border-b border-gray-200"> <div class="text-sm text-gray-900"> {{ $post->title }} </div> </td> <td class="px-6 py-4 border-b border-gray-200"> <button wire:click="edit({{ $post->id }})" class="px-4 py-2 text-white bg-blue-600"> Edit </button> </td> <td class="px-6 py-4 text-sm text-gray-500 border-b border-gray-200"> <button wire:click="destroy({{ $post->id }})" class="px-4 py-2 text-white bg-red-600"> Delete </button> </td> </tr> @endforeach </tbody> </table> </div> {{ $posts->links() }} </div> </div> </div></div>
- Running the application Now let's serve the application
php artisan serve
Then you can visit 127.0.0.1:8000
- Everything should work as normal, please share this posts If it's helpful to you.
- If you have issued with this post, please reach me on twitter
@iamputhea