Today we will create a Laravel application to perform crud operations (create, read, update, upload, and delete) with Laravel 8 and Livewire using laravel breeze. Why is breeze not jetstream, Because laravel breeze is much simple and it easy to understand also it come with tailwind and alpinejs. So let start.
Laravel Livewire Crud with Breeze & Tailwind CSS Example
Step 1: Create Laravel Project
Step 2: Set Up Database Details in ENV
Step 3: Install breeze & Setup Livewire
Step 4: Perform CRUD Operations
Step 5: Serve The Application
Step 1: Create Laravel Project
Installing a fresh new laravel application.
composer create-project --prefer-dist laravel/laravel project-name
Step 2: Set Up Database Details in ENV
Now, you have to connect the laravel app to the database, hence open the .env configuration file and add the database credentials as suggested below.
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user_name
DB_PASSWORD=database_password
Step 3: Install breeze & Setup Livewire
Install breeze
You need to install first breeze package
composer require laravel/breeze --dev
Then, install breeze ui
php artisan breeze:install
Install livewire
composer require livewire/livewire
Include the JavaScript (on every page that will be using Livewire).
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', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:[email protected];600;700&display=swap">
<!-- Styles -->
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
@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>
@livewireScripts
</body>
</html>
You can install dependencies
npm install && npm run dev
Step 4: Perform CRUD operations
Create Model and Migration
php artisan make:model Post -m
Migration File
<?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');
}
}
Model File
app/Models/Post.php
<?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'
];
}
php artisan migrate
Create Post Controller
php artisan make:controller PostController
app/Http/Controllers/PostController.php
<?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('posts');
}
}
Create Route
<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('posts', [PostController::class,'index'])->name('posts.index');
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
require __DIR__ . '/auth.php';
Create Livewire Component
php artisan make:livewire PostForm
COMPONENT CREATED 🤙
CLASS: app/Http/Livewire/PostForm.php
VIEW: resources/views/livewire/post-form.blade.php
Use Component file.
resources/views/postsblade.php
<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-form />
</div>
</div>
</div>
</div>
</x-app-layout>
Next you need to update PostForm.php file.
app/Http/Livewire/PostForm.php
<?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-form', ['posts' => Post::latest()->paginate(10)]);
}
}
Use View File
resources/views/livewire/post-form.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>
Step 5: Serve The Application
Now, your application let’s serve the application.
php artisan serve
Now you have to open bellow URL with your browser:
http://localhost:8000/posts