KelasIT.com
Web Development

Cara Membuat CRUD Menggunakan Laravel

Tutorial langkah demi langkah membuat fitur CRUD (Create, Read, Update, Delete) di Laravel lengkap dengan migration, model, controller, route, validasi, dan view Blade.

Cara Membuat CRUD Menggunakan Laravel

CRUD adalah singkatan dari Create, Read, Update, Delete: empat operasi dasar pada data. Hampir setiap aplikasi web berisi CRUD, baik untuk produk, artikel, maupun pengguna. Pada tutorial ini kita membuat CRUD Artikel di Laravel dari awal sampai bisa dipakai.

Prasyarat: Laravel sudah terpasang dan terhubung ke database (atur DB_* di file .env).

Langkah 1: Membuat model, migration, dan controller

php artisan make:model Post -mc --resource

Perintah ini membuat app/Models/Post.php, file migration, dan PostController berisi method resource (index, create, store, show, edit, update, destroy).

Langkah 2: Mendefinisikan tabel

Buka file migration di database/migrations/ lalu isi method up():

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();
});

Jalankan:

php artisan migrate

Langkah 3: Mengatur model

Agar kolom boleh diisi secara massal (create dan update), daftarkan di $fillable:

class Post extends Model
{
    protected $fillable = ['title', 'body'];
}

Ini adalah perlindungan mass assignment: hanya kolom yang kamu daftarkan yang boleh diisi dari input pengguna.

Langkah 4: Mendaftarkan route

Di routes/web.php, satu baris cukup untuk membuat ketujuh route CRUD:

use App\Http\Controllers\PostController;

Route::resource('posts', PostController::class);

Lihat daftarnya dengan php artisan route:list.

Langkah 5: Menulis controller

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::latest()->paginate(10);
        return view('posts.index', compact('posts'));
    }

    public function create()
    {
        return view('posts.create');
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'title' => 'required|max:150',
            'body'  => 'required',
        ]);

        Post::create($data);

        return redirect()->route('posts.index')
            ->with('success', 'Artikel berhasil dibuat.');
    }

    public function edit(Post $post)
    {
        return view('posts.edit', compact('post'));
    }

    public function update(Request $request, Post $post)
    {
        $data = $request->validate([
            'title' => 'required|max:150',
            'body'  => 'required',
        ]);

        $post->update($data);

        return redirect()->route('posts.index')
            ->with('success', 'Artikel berhasil diperbarui.');
    }

    public function destroy(Post $post)
    {
        $post->delete();

        return redirect()->route('posts.index')
            ->with('success', 'Artikel dihapus.');
    }
}

Beberapa hal penting:

  • Post $post pada parameter memakai route model binding: Laravel otomatis mengambil data berdasarkan ID di URL dan menampilkan 404 jika tidak ada.
  • validate() menghentikan proses dan mengembalikan pengguna ke form beserta pesan error jika data tidak valid.
  • paginate(10) membagi hasil menjadi halaman berisi 10 data.

Langkah 6: Membuat view

Buat resources/views/posts/index.blade.php:

@if (session('success'))
    <p>{{ session('success') }}</p>
@endif

<a href="{{ route('posts.create') }}">Tambah artikel</a>

<table>
    @foreach ($posts as $post)
    <tr>
        <td>{{ $post->title }}</td>
        <td>
            <a href="{{ route('posts.edit', $post) }}">Ubah</a>
            <form method="POST" action="{{ route('posts.destroy', $post) }}"
                 >
                @csrf
                @method('DELETE')
                <button>Hapus</button>
            </form>
        </td>
    </tr>
    @endforeach
</table>

{{ $posts->links() }}

Dan form di posts/create.blade.php:

<form method="POST" action="{{ route('posts.store') }}">
    @csrf
    <input name="title" value="{{ old('title') }}">
    @error('title') <small>{{ $message }}</small> @enderror

    <textarea name="body">{{ old('body') }}</textarea>
    @error('body') <small>{{ $message }}</small> @enderror

    <button>Simpan</button>
</form>

Catatan wajib:

  • @csrf melindungi form dari serangan CSRF. Tanpa itu Laravel menolak permintaan (error 419).
  • HTML hanya mengenal GET dan POST, sehingga @method('DELETE') dan @method('PUT') dipakai untuk "meminjam" method lain.
  • {{ }} otomatis meng-escape HTML sehingga aman dari XSS.
  • old('title') mempertahankan isian saat validasi gagal.

Kesalahan yang paling sering terjadi

GejalaPenyebab umum
419 Page ExpiredLupa @csrf di form
MassAssignmentExceptionKolom belum masuk $fillable
405 Method Not AllowedLupa @method('PUT'/'DELETE')
Column not foundMigration belum dijalankan atau nama kolom salah
Data tidak berubahKolom tidak ada di input atau $fillable

Pengembangan lanjutan

  • Pindahkan aturan validasi ke Form Request (php artisan make:request StorePostRequest).
  • Tambahkan pencarian dan filter dengan when() pada query.
  • Tambahkan upload gambar dengan $request->file('image')->store('posts', 'public').
  • Batasi akses dengan middleware auth dan policy.
  • Gunakan soft delete agar data yang dihapus bisa dipulihkan.

Mengatur layout agar tidak menyalin HTML

Alih-alih mengulang <html>, <head>, dan navigasi di setiap view, buat satu layout:

{{-- resources/views/layouts/app.blade.php --}}
<!doctype html>
<html>
<head><title>@yield('title')</title></head>
<body>
    <nav>...</nav>
    @yield('content')
</body>
</html>
{{-- resources/views/posts/index.blade.php --}}
@extends('layouts.app')
@section('title', 'Daftar Artikel')
@section('content')
    ...isi halaman...
@endsection

Menambahkan pencarian

public function index(Request $request)
{
    $posts = Post::query()
        ->when($request->q, fn ($query, $q) => $query->where('title', 'like', "%{$q}%"))
        ->latest()
        ->paginate(10)
        ->withQueryString();      // pencarian tetap ada saat pindah halaman

    return view('posts.index', compact('posts'));
}

when() hanya menambah kondisi bila q terisi, sehingga kode tidak berantakan oleh if.

Upload gambar pada CRUD

Tambahkan kolom image (nullable) di migration, ubah form menjadi enctype="multipart/form-data", lalu:

$data = $request->validate([
    'title' => 'required|max:150',
    'body'  => 'required',
    'image' => 'nullable|image|max:2048',
]);

if ($request->hasFile('image')) {
    $data['image'] = $request->file('image')->store('posts', 'public');
}

Jangan lupa php artisan storage:link, dan hapus berkas lama saat gambar diganti atau data dihapus.

Merapikan dengan Form Request

php artisan make:request PostRequest
class PostRequest extends FormRequest
{
    public function authorize(): bool { return true; }

    public function rules(): array
    {
        return [
            'title' => ['required', 'max:150'],
            'body'  => ['required'],
        ];
    }

    public function messages(): array
    {
        return ['title.required' => 'Judul wajib diisi.'];
    }
}

Lalu controller cukup menulis store(PostRequest $request) dan memakai $request->validated(). Aturan yang sama dipakai untuk store dan update.

Latihan untuk menguatkan pemahaman

  1. Tambahkan kolom slug dan tampilkan artikel lewat URL /posts/judul-artikel.
  2. Tambahkan fitur filter berdasarkan kategori (butuh relasi, lihat Mengenal Eloquent Relationship).
  3. Batasi agar hanya pengguna yang login yang boleh membuat dan menghapus (Membuat Authentication Laravel).
  4. Ubah penghapusan menjadi soft delete dan buat halaman "sampah" untuk memulihkan data.
  5. Buat versi API-nya dengan Route::apiResource (Membuat REST API dengan Laravel).

Kesimpulan

Alur CRUD Laravel selalu sama: migration → model → route → controller → view. Setelah memahaminya sekali, kamu bisa membuat modul apa pun dengan pola yang identik.

H
Hifzon

Menulis tentang pemrograman, database, AI, dan karier di dunia IT supaya belajar terasa lebih mudah dan menyenangkan.

Komentar (0)

Komentar hanya untuk member. Masuk atau daftar gratis untuk ikut berdiskusi.

Mau belajar lebih dalam?

Course online dengan latihan coding interaktif dan sertifikat.

Lihat Course →

Gabung komunitas

Tanya jawab, info event, dan teman belajar di grup WhatsApp.

Gabung Grup