In this section we will create posts blog app with category crud. We will see store crud app data with category.
Step 1: Create Laravel Project
Run below command to create laravel app.
composer create-project Laravel/laravel blog
Step 2: Install Laravel Breeze
Install laravel breeze for auth and tailwind css & alpine js.
composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev
php artisan migrate
Step 3: Create Category Modal Migration and Seeder
run command to create category modal and migration file.
php artisan make:model Category -m
create_categories_table.php
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug');
$table->timestamps();
});
}
Models/Category.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',
];
}
Insert data in category seeder.
database/seeders/CategorySeeder.php
<?php
namespace Database\Seeders;
use App\Models\Category;
use Illuminate\Database\Seeder;
class CategorySeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$data = [
[
'name' => 'PHP',
'slug' => \Str::slug('PHP'),
'created_at' => now(),
],
[
'name' => 'Python',
'slug' => \Str::slug('Python'),
'created_at' => now(),
],
[
'name' => 'Java',
'slug' => \Str::slug('Java'),
'created_at' => now(),
],
[
'name' => 'C++',
'slug' => \Str::slug('C++'),
'created_at' => now(),
],
[
'name' => 'Ruby',
'slug' => \Str::slug('Ruby'),
'created_at' => now(),
],
];
Category::insert($data);
}
}
Step 4: Create Post Modal Migration Controller and Route
run below command to create post modal, migration and controller
php artisan make:model Post -mcr
create_posts_table.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug');
$table->longText('description');
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
}
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',
'slug',
'description',
'category_id',
];
public function category()
{
return $this->belongsTo(Category::class);
}
}
routes/web.php
Route::resource('posts', PostController::class);
app/Http/Controllers/PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Category;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::with('category')->latest()->paginate(10);
return view('posts.index', compact('posts'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$categories = Category::all();
return view('posts.create', compact('categories'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'slug' => 'required|string|max:255',
'description' => 'required',
'category_id' => 'required|exists:App\Models\Category,id'
]);
Post::create([
'title' => $request->title,
'slug' => \Str::slug($request->slug),
'description' => $request->description,
'category_id' => $request->category_id,
]);
return redirect()->route('posts.index')->with('status', 'Post Created Successfully');
}
/**
* Display the specified resource.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
$categories = Category::all();
return view('posts.edit', compact('categories', 'post'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Post $post)
{
$request->validate([
'title' => 'required|string|max:255',
'slug' => 'required|string|max:255',
'description' => 'required',
'category_id' => 'required|exists:App\Models\Category,id',
]);
$post->title = $request->title;
$post->slug = \Str::slug($request->slug);
$post->description = $request->description;
$post->category_id = $request->category_id;
$post->save();
return redirect()->route('posts.index')->with('status', 'Post Updated Successfully');
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')->with('status', 'Post Delete Successfully');
}
}
Step 5:Perform CRUD Operation with Category
posts/create.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Post Create') }}
</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">
<form method="POST" action="{{ route('posts.store') }}">
@csrf
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Title</span>
<input type="text" name="title"
class="block w-full @error('title') border-red-500 @enderror mt-1 rounded-md"
placeholder="" value="{{old('title')}}" />
</label>
@error('title')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Slug</span>
<input type="text" name="slug"
class="block w-full @error('slug') border-red-500 @enderror mt-1 rounded-md"
placeholder="" value="{{old('slug')}}" />
</label>
@error('slug')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<div class="mb-6 ">
<label class="block">
<span class="text-gray-700">Select Category</span>
<select name="category_id" class="block w-full mt-1 rounded-md">
@foreach ($categories as $category)
<option value="{{$category->id}}">{{$category->name}}</option>
@endforeach
</select>
</label>
@error('category_id')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Description</span>
<textarea class="block w-full mt-1 rounded-md" name="description"
rows="3">{{old('description')}}</textarea>
</label>
@error('description')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<button type="submit"
class="text-white bg-blue-600 rounded text-sm px-5 py-2.5">Submit</button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
posts/index.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Posts') }}
</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">
<div x-data="{ showMessage: true }" x-show="showMessage" class="flex justify-center">
@if (session()->has('status'))
<div
class="flex items-center justify-between max-w-xl p-4 bg-white border rounded-md shadow-sm">
<div class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="w-8 h-8 text-green-500"
viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clip-rule="evenodd" />
</svg>
<p class="ml-3 text-sm font-bold text-green-600">{{ session()->get('status') }}</p>
</div>
<span @click="showMessage = false" class="inline-flex items-center cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 text-gray-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
</div>
@endif
</div>
<div class="mt-1 mb-4">
<a class="px-2 py-2 text-sm text-white bg-blue-600 rounded"
href="{{ route('posts.create') }}">{{ __('Add Post') }}</a>
</div>
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">
#
</th>
<th scope="col" class="px-6 py-3">
Name
</th>
<th scope="col" class="px-6 py-3">
Category
</th>
<th scope="col" class="px-6 py-3">
Edit
</th>
<th scope="col" class="px-6 py-3">
Show
</th>
<th scope="col" class="px-6 py-3">
Delete
</th>
</tr>
</thead>
<tbody>
@foreach ($posts as $post)
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
<th scope="row"
class="px-6 py-4 font-medium text-gray-900 dark:text-white whitespace-nowrap">
{{$post->id}}
</th>
<td class="px-6 py-4">
{{$post->title}}
</td>
<td class="px-6 py-4">
{{$post->category->name}}
</td>
<td class="px-6 py-4">
<a href="{{ route('posts.edit',$post->id) }}">Edit</a>
</td>
<td class="px-6 py-4">
<a href="{{ route('posts.show',$post->id) }}">Show</a>
</td>
<td class="px-6 py-4">
<form action="{{ route('posts.destroy',$post->id) }}" method="POST"
onsubmit="return confirm('{{ trans('are You Sure ? ') }}');"
style="display: inline-block;">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class="px-4 py-2 text-white bg-red-700 rounded"
value="Delete">
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
posts/edit.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Category Edit') }}
</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">
<form method="POST" action="{{ route('posts.update',$post->id) }}">
@csrf
@method('put')
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Title</span>
<input type="text" name="title"
class="block w-full @error('title') border-red-500 @enderror mt-1 rounded-md"
placeholder="" value="{{old('title',$post->title)}}" />
</label>
@error('title')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Slug</span>
<input type="text" name="slug"
class="block w-full @error('slug') border-red-500 @enderror mt-1 rounded-md"
placeholder="" value="{{old('slug',$post->slug)}}" />
</label>
@error('slug')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Select Category</span>
<select name="category_id" class="block w-full mt-1 rounded-md">
@foreach ($categories as $category)
<option @selected($category->id == $post->category_id)
value="{{$category->id}}">{{$category->name}}</option>
@endforeach
</select>
</label>
@error('category_id')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700">Description</span>
<textarea class="block w-full mt-1 rounded-md" name="description"
rows="3">{{ $post->description}}</textarea>
</label>
@error('description')
<div class="text-sm text-red-600">{{ $message }}</div>
@enderror
</div>
<button type="submit"
class="text-white bg-blue-600 rounded text-sm px-5 py-2.5">Submit</button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
Step 6:Run laravel and vite server
php artisan serve
//and
npm run dev
Read Also
Laravel 9 Add Simple Sidebar with Tailwind CSS Example
How to Use Carousel Slider in Laravel 9 Example
Laravel 9 Posts with Tags Many to Many Relationships Example
How to Use Ckeditor 5 in Laravel 9 Vite with Tailwind CSS
Laravel 9 Simple Image Upload in Ckeditor 5 Example
Laravel 9 Flash Message Timeout and Hide Message Example
Install & Setup Markdown Editor in Laravel 9
Nuxt 3 Data Fetching Using Laravel 9 Api Example
Laravel 9 Image Upload with Preview using Tailwind CSS & Alpine JS
Laravel 9 with Tailwind CSS Form Validation Example
Laravel 9 Backend Api Connect with Vue 3 Using Axios Example
Laravel 9 Authentication with Next js Example
Laravel 9 Sanctum Authentication with Nuxt JS Example
Laravel 9 Simple Search with Pagination Example
Laravel 9 Install Setup TALL(Tailwind, Alpinejs, Livewire) Admin Panel
How to Fix and Clean Code Style in laravel 9
Laravel 9 Image File Upload Example
3 Way to Create Slug in Laravel 9 without Package
How to Add Dark Mode in Laravel 9 with Tailwind CSS