Resource Controller

Di PHP Native, kamu membuat file terpisah untuk setiap operasi: create.php, update.php, delete.php. Di Laravel, semua operasi CRUD bisa dikelola dalam satu controller dengan konvensi penamaan yang rapi.

Inilah Resource Controller — controller yang mengikuti 7 method standar Laravel.

1. Membuat Resource Controller

# Buat controller dengan 7 method standar
php artisan make:controller ProdukController --resource

Artisan akan membuat controller dengan method-method ini:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProdukController extends Controller
{
    // 1. Tampilkan daftar semua produk
    public function index()
    {
        $produkList = Produk::latest()->paginate(10);
        return view('produk.index', compact('produkList'));
    }

    // 2. Tampilkan form untuk membuat produk baru
    public function create()
    {
        return view('produk.create');
    }

    // 3. Simpan produk baru ke database
    public function store(Request $request)
    {
        $validated = $request->validate([
            'nama'  => 'required|string|max:255',
            'harga' => 'required|numeric|min:1000',
        ]);

        Produk::create($validated);

        return redirect()->route('produk.index')
            ->with('success', 'Produk berhasil ditambahkan!');
    }

    // 4. Tampilkan detail satu produk
    public function show(Produk $produk)
    {
        return view('produk.show', compact('produk'));
    }

    // 5. Tampilkan form untuk edit produk
    public function edit(Produk $produk)
    {
        return view('produk.edit', compact('produk'));
    }

    // 6. Update produk di database
    public function update(Request $request, Produk $produk)
    {
        $validated = $request->validate([
            'nama'  => 'required|string|max:255',
            'harga' => 'required|numeric|min:1000',
        ]);

        $produk->update($validated);

        return redirect()->route('produk.index')
            ->with('success', 'Produk berhasil diupdate!');
    }

    // 7. Hapus produk dari database
    public function destroy(Produk $produk)
    {
        $produk->delete();

        return redirect()->route('produk.index')
            ->with('success', 'Produk berhasil dihapus!');
    }
}

2. Mendaftarkan Resource Route

Di PHP Native, kamu harus mendaftarkan setiap URL satu per satu. Di Laravel, cukup satu baris:

// routes/web.php

use App\Http\Controllers\ProdukController;

// Satu baris ini menghasilkan 7 route sekaligus!
Route::resource('produk', ProdukController::class);

Yang akan menghasilkan:

MethodURIActionNama Route
GET/produkindex()produk.index
GET/produk/createcreate()produk.create
POST/produkstore()produk.store
GET/produk/{produk}show()produk.show
GET/produk/{produk}/editedit()produk.edit
PUT/PATCH/produk/{produk}update()produk.update
DELETE/produk/{produk}destroy()produk.destroy

Kamu bisa melihat semua route yang terdaftar dengan:

php artisan route:list

3. Route Model Binding

Perhatikan parameter Produk $produk di method seperti show() dan edit(). Ini namanya Route Model Binding — Laravel otomatis mencari data di database berdasarkan ID di URL.

// Tanpa Route Model Binding (cara manual)
public function show($id)
{
    $produk = Produk::findOrFail($id); // Manual cari di DB
    return view('produk.show', compact('produk'));
}

// Dengan Route Model Binding (cara Laravel!)
public function show(Produk $produk) // Laravel otomatis cari berdasarkan ID
{
    return view('produk.show', compact('produk'));
}

Jika URL-nya /produk/5, Laravel otomatis menjalankan Produk::findOrFail(5). Jika produk dengan ID 5 tidak ada → otomatis 404.

Named Routes

Gunakan route() helper untuk membuat URL dari nama route:

// Di Blade
<a href="{{ route('produk.show', $produk) }}">Lihat Detail</a>
<a href="{{ route('produk.edit', $produk) }}">Edit</a>

// Di Controller
return redirect()->route('produk.index');

Keuntungannya: kalau kamu ubah URL dari /produk ke /barang, semua link otomatis ikut berubah!

<!-- resources/views/produk/index.blade.php -->

<h1>Daftar Produk</h1>

<a href="{{ route('produk.create') }}">+ Tambah Produk</a>

@foreach ($produkList as $produk)
    <div style="border: 1px solid #ddd; padding: 1rem; margin: 0.5rem 0;">
        <h3>{{ $produk->nama }}</h3>
        <p>Rp {{ number_format($produk->harga, 0, ',', '.') }}</p>

        <a href="{{ route('produk.show', $produk) }}">Detail</a>
        <a href="{{ route('produk.edit', $produk) }}">Edit</a>

        {{-- Form delete (karena DELETE butuh method spoofing) --}}
        <form action="{{ route('produk.destroy', $produk) }}" method="POST"
              style="display: inline;"
              onsubmit="return confirm('Yakin mau hapus?')">
            @csrf
            @method('DELETE')
            <button type="submit" style="color: red;">Hapus</button>
        </form>
    </div>
@endforeach

{{ $produkList->links() }} {{-- Pagination otomatis! --}}
Method Spoofing

HTML form hanya mendukung GET dan POST. Untuk PUT, PATCH, dan DELETE, Laravel menggunakan method spoofing: tambahkan @method('PUT') atau @method('DELETE') di dalam form. Jangan lupa @csrf untuk perlindungan CSRF! Kalau request tetap ditolak, cek CSRF Token Mismatch di Laravel.

5. Membatasi Method dengan only() dan except()

Kadang kamu tidak butuh semua 7 method:

// Hanya daftarkan route yang dibutuhkan
Route::resource('produk', ProdukController::class)
    ->only(['index', 'show']); // Hanya lihat, tanpa bisa tambah/edit/hapus

// Atau kebalikannya — semua kecuali...
Route::resource('produk', ProdukController::class)
    ->except(['destroy']); // Semua kecuali hapus

6. Nested Resources

Untuk relasi data, misalnya produk punya review:

Route::resource('produk.review', ReviewController::class);

Ini akan membuat URL seperti:

  • GET /produk/{produk}/review → Semua review produk tertentu
  • POST /produk/{produk}/review → Tambah review ke produk
  • DELETE /produk/{produk}/review/{review} → Hapus review

7. Perbandingan: PHP Native vs Laravel

AspekPHP NativeLaravel Resource Controller
File1 file per operasi (5+ file)1 controller, 7 method
URLAtur manual satu per satuRoute::resource() — 1 baris = 7 route
Cari Data$_GET['id'] + query manualRoute Model Binding otomatis
KonvensiBebas (sering tidak konsisten)index, create, store, show, edit, update, destroy
PaginationManual dengan LIMIT OFFSET->paginate(10) + ->links()

Selanjutnya

Kamu sudah bisa membuat CRUD yang rapi! Selanjutnya, bagaimana cara memastikan kode-mu berjalan benar? Lanjut ke Testing dengan Pest → untuk belajar menulis tes otomatis.

Troubleshooting Resource Route

Kalau route resource kamu menampilkan 404 yang aneh, model tidak pernah ter-resolve otomatis, migration gagal, atau file Blade tidak ditemukan, cek: