TIPS#1 CRUD Laravel 12
Dipublikasikan pada oleh Admin
CRUD (Create, Read, Update, Delete) adalah fondasi pengelolaan data pada aplikasi web. Artikel ini memandu Anda membangun CRUD sederhana di Laravel 12 dari nol hingga tampil di Blade. Buat proyek baru: Atau dengan Laravel installer: Atur koneksi di Gunakan artisan untuk membuat paket CRUD bernama Buka file migration Jalankan migrasi: Tambahkan Daftarkan route resource di Implementasikan method standar di Aktifkan Bootstrap pagination di Buka Anda baru saja membuat CRUD lengkap di Laravel 12: mulai dari migration, model, controller, route resource, hingga tampilan Blade. Selanjutnya Anda bisa menambah fitur seperti pencarian, filter, upload file, atau validasi lanjutan menggunakan Form Request.Tutorial CRUD Laravel 12: Panduan Lengkap untuk Pemula
Prasyarat
1) Instalasi Laravel
composer create-project laravel/laravel crud-laravel12
cd crud-laravel12
laravel new crud-laravel12
2) Konfigurasi Database
.env lalu buat database bernama crud_laravel12 di MySQL.DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crud_laravel12
DB_USERNAME=root
DB_PASSWORD=
3) Generate Model, Migration, Controller
Post:php artisan make:model Post -mcr
app/Models/Post.phpdatabase/migrations/<timestamp>_create_posts_table.phpapp/Http/Controllers/PostController.php4) Definisi Skema Tabel (Migration)
create_posts_table.php dan sesuaikan:<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down(): void {
Schema::dropIfExists('posts');
}
};
php artisan migrate
5) Model & Mass Assignment
$fillable agar field bisa diisi mass-assignment:<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'content'];
}
6) Routing Resource
routes/web.php:<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
7) Controller CRUD
app/Http/Controllers/PostController.php:<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->paginate(5);
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')
->with('success', 'Post berhasil ditambahkan.');
}
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')
->with('success', 'Post berhasil diperbarui.');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()
->route('posts.index')
->with('success', 'Post berhasil dihapus.');
}
}
8) Blade Views (layout, index, form)
8.1 Layout Utama —
resources/views/layouts/app.blade.php<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel 12 CRUD</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4">
@yield('content')
</div>
</body>
</html>
8.2 Index —
resources/views/posts/index.blade.php@extends('layouts.app')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-3">
<h2 class="mb-0">Daftar Post</h2>
<a href="{{ route('posts.create') }}" class="btn btn-primary">Tambah Post</a>
</div>
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<table class="table table-bordered align-middle">
<thead>
<tr>
<th style="width:70px">No</th>
<th>Judul</th>
<th style="width:220px">Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($posts as $post)
<tr>
<td>{{ $loop->iteration + ($posts->currentPage()-1)*$posts->perPage() }}</td>
<td>{{ $post->title }}</td>
<td>
<a href="{{ route('posts.show', $post) }}" class="btn btn-sm btn-info">Lihat</a>
<a href="{{ route('posts.edit', $post) }}" class="btn btn-sm btn-warning">Edit</a>
<form action="{{ route('posts.destroy', $post) }}" method="POST" class="d-inline" onsubmit="return confirm('Yakin hapus?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">Hapus</button>
</form>
</td>
</tr>
@empty
<tr><td colspan="3" class="text-center">Belum ada data.</td></tr>
@endforelse
</tbody>
</table>
{{ $posts->links() }}
@endsection
8.3 Form Create —
resources/views/posts/create.blade.php@extends('layouts.app')
@section('content')
<h2 class="mb-3">Tambah Post</h2>
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('posts.store') }}" method="POST" class="vstack gap-3">
@csrf
<div>
<label class="form-label">Judul</label>
<input type="text" name="title" class="form-control" value="{{ old('title') }}" required>
</div>
<div>
<label class="form-label">Konten</label>
<textarea name="content" rows="6" class="form-control" required>{{ old('content') }}</textarea>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('posts.index') }}" class="btn btn-secondary">Batal</a>
</div>
</form>
@endsection
8.4 Form Edit —
resources/views/posts/edit.blade.php@extends('layouts.app')
@section('content')
<h2 class="mb-3">Edit Post</h2>
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('posts.update', $post) }}" method="POST" class="vstack gap-3">
@csrf
@method('PUT')
<div>
<label class="form-label">Judul</label>
<input type="text" name="title" class="form-control" value="{{ old('title', $post->title) }}" required>
</div>
<div>
<label class="form-label">Konten</label>
<textarea name="content" rows="6" class="form-control" required>{{ old('content', $post->content) }}</textarea>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Perbarui</button>
<a href="{{ route('posts.index') }}" class="btn btn-secondary">Batal</a>
</div>
</form>
@endsection
8.5 Show —
resources/views/posts/show.blade.php@extends('layouts.app')
@section('content')
<h2 class="mb-3">Detail Post</h2>
<div class="card">
<div class="card-body">
<h4 class="card-title mb-3">{{ $post->title }}</h4>
<article class="card-text">{{ $post->content }}</article>
</div>
</div>
<div class="mt-3 d-flex gap-2">
<a href="{{ route('posts.edit', $post) }}" class="btn btn-warning">Edit</a>
<a href="{{ route('posts.index') }}" class="btn btn-secondary">Kembali</a>
</div>
@endsection
Opsional: Pagination Bootstrap 5
App\Providers\AppServiceProvider.php:use Illuminate\Pagination\Paginator;
public function boot(): void
{
Paginator::useBootstrapFive();
}
9) Menjalankan Aplikasi
php artisan serve
http://127.0.0.1:8000/posts untuk mencoba CRUD.Penutup