Langsung ke konten
KamusNgoding
Pemula Laravel 4 menit baca

Routing dan Controller di Laravel: Panduan Lengkap

#laravel #routing #controller #resource-controller #middleware #pemula

Pendahuluan

Setelah berhasil menginstall Laravel, pertanyaan berikutnya adalah: bagaimana cara kerja URL di Laravel?

Ketika seseorang mengakses https://taskmanager.com/tasks, bagaimana Laravel tahu kode mana yang harus dijalankan? Inilah tugas Router — pengarah lalu lintas yang menentukan kode apa yang dipanggil untuk setiap URL.

Di artikel ini kamu akan memahami:

  • Cara mendefinisikan route dasar
  • Parameter URL dinamis
  • Named routes dan URL generation
  • Controller dan cara membuatnya
  • Resource Controller untuk CRUD
  • Route Group dan Middleware

Mari kita mulai dengan membuka file routes/web.php di proyek task-manager.


Routing Dasar

File routes/web.php adalah tempat kamu mendefinisikan semua URL yang bisa diakses oleh pengguna melalui browser.

<?php
// routes/web.php

use Illuminate\Support\Facades\Route;

// Route paling sederhana — tampilkan teks
Route::get('/hello', function () {
    return 'Halo, dunia!';
});

// Tampilkan view Blade
Route::get('/', function () {
    return view('welcome');
});

// Return JSON (cocok untuk testing)
Route::get('/info', function () {
    return ['status' => 'ok', 'laravel' => app()->version()];
});

HTTP Methods yang Didukung

Laravel mendukung semua HTTP method:

Route::get('/tasks', function () { /* tampilkan daftar */ });
Route::post('/tasks', function () { /* simpan data baru */ });
Route::put('/tasks/{id}', function ($id) { /* update data */ });
Route::patch('/tasks/{id}', function ($id) { /* partial update */ });
Route::delete('/tasks/{id}', function ($id) { /* hapus data */ });

// Merespons semua method HTTP
Route::any('/webhook', function () { /* handle semua */ });

// Merespons beberapa method sekaligus
Route::match(['get', 'post'], '/contact', function () {
    // handle GET (tampil form) dan POST (proses form)
});

Parameter URL

URL seringkali membutuhkan nilai dinamis, seperti ID artikel atau username pengguna.

Parameter Wajib

// {id} adalah parameter yang wajib ada
Route::get('/tasks/{id}', function (string $id) {
    return "Menampilkan task #" . $id;
});

// Akses: /tasks/42  → "Menampilkan task #42"
// Akses: /tasks     → 404 Not Found

Parameter Opsional

// {name?} adalah parameter opsional (ada tanda tanya)
Route::get('/user/{name?}', function (string $name = 'Tamu') {
    return "Halo, " . $name . "!";
});

// Akses: /user/Budi  → "Halo, Budi!"
// Akses: /user       → "Halo, Tamu!"

Validasi Parameter dengan Regex

// Hanya menerima angka
Route::get('/tasks/{id}', function (string $id) {
    return "Task #" . $id;
})->where('id', '[0-9]+');

// Hanya menerima huruf
Route::get('/user/{name}', function (string $name) {
    return "User: " . $name;
})->where('name', '[A-Za-z]+');

// Menggunakan helper method
Route::get('/tasks/{id}', function ($id) {})->whereNumber('id');
Route::get('/user/{name}', function ($name) {})->whereAlpha('name');

Named Routes

Named routes memungkinkan kamu membuat URL menggunakan nama route, bukan string URL langsung. Ini sangat berguna agar jika URL berubah, kamu tidak perlu mengubah kode di banyak tempat.

// Beri nama pada route
Route::get('/tasks', [TaskController::class, 'index'])->name('tasks.index');
Route::get('/tasks/{id}', [TaskController::class, 'show'])->name('tasks.show');
Route::get('/tasks/create', [TaskController::class, 'create'])->name('tasks.create');
// Gunakan di Controller atau Blade
$url = route('tasks.index');         // http://localhost:8000/tasks
$url = route('tasks.show', ['id' => 42]);  // http://localhost:8000/tasks/42
{{-- Di file Blade --}}
<a href="{{ route('tasks.index') }}">Daftar Task</a>
<a href="{{ route('tasks.show', ['id' => $task->id]) }}">Detail Task</a>

Controller

Sampai sini, kita masih menulis logika langsung di file route (closure). Untuk aplikasi sungguhan, ini tidak ideal. Controller memisahkan logika ke file tersendiri sehingga lebih terorganisir.

Membuat Controller

# Buat controller menggunakan Artisan
php artisan make:controller TaskController

# File dibuat di: app/Http/Controllers/TaskController.php
<?php
// app/Http/Controllers/TaskController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TaskController extends Controller
{
    // Method index — tampilkan daftar task
    public function index()
    {
        return view('tasks.index');
    }

    // Method show — tampilkan detail task
    public function show(string $id)
    {
        return view('tasks.show', ['id' => $id]);
    }
}

Menghubungkan Route ke Controller

<?php
// routes/web.php

use App\Http\Controllers\TaskController;

Route::get('/tasks', [TaskController::class, 'index'])->name('tasks.index');
Route::get('/tasks/{id}', [TaskController::class, 'show'])->name('tasks.show');

Sintaks [TaskController::class, 'index'] berarti “panggil method index dari class TaskController”.


Resource Controller — CRUD dalam Satu Perintah

Untuk operasi CRUD (Create, Read, Update, Delete), Laravel menyediakan Resource Controller yang secara otomatis membuat 7 method standar.

# Buat resource controller
php artisan make:controller TaskController --resource

# Untuk sekaligus dengan model:
php artisan make:controller TaskController --model=Task --resource

Resource Controller yang dibuat memiliki 7 method:

class TaskController extends Controller
{
    // GET /tasks
    public function index() { /* tampilkan semua task */ }

    // GET /tasks/create
    public function create() { /* tampilkan form buat task baru */ }

    // POST /tasks
    public function store(Request $request) { /* simpan task baru */ }

    // GET /tasks/{task}
    public function show(Task $task) { /* tampilkan detail task */ }

    // GET /tasks/{task}/edit
    public function edit(Task $task) { /* tampilkan form edit */ }

    // PUT/PATCH /tasks/{task}
    public function update(Request $request, Task $task) { /* update task */ }

    // DELETE /tasks/{task}
    public function destroy(Task $task) { /* hapus task */ }
}

Mendaftarkan Route Resource

Satu baris ini menggantikan 7 route sekaligus!

// routes/web.php
Route::resource('tasks', TaskController::class);

Jalankan php artisan route:list untuk melihat semua route yang dibuat:

GET    /tasks           → TaskController@index    (tasks.index)
GET    /tasks/create    → TaskController@create   (tasks.create)
POST   /tasks           → TaskController@store    (tasks.store)
GET    /tasks/{task}    → TaskController@show     (tasks.show)
GET    /tasks/{task}/edit → TaskController@edit   (tasks.edit)
PUT    /tasks/{task}    → TaskController@update   (tasks.update)
DELETE /tasks/{task}    → TaskController@destroy  (tasks.destroy)

Membatasi Method Resource

Jika tidak membutuhkan semua 7 method:

// Hanya index, create, store, show
Route::resource('tasks', TaskController::class)->only(['index', 'create', 'store', 'show']);

// Semua kecuali create dan edit (cocok untuk API)
Route::resource('tasks', TaskController::class)->except(['create', 'edit']);

Single Action Controller

Untuk aksi yang sangat sederhana dan hanya punya satu method, gunakan Single Action Controller dengan method __invoke:

php artisan make:controller WelcomeController --invokable
class WelcomeController extends Controller
{
    public function __invoke()
    {
        return view('welcome');
    }
}
// Route yang lebih bersih
Route::get('/', WelcomeController::class);

Route Group

Route Group berguna untuk mengelompokkan route yang memiliki prefix, middleware, atau namespace yang sama.

Group dengan Prefix URL

// Semua route di dalam group ini akan memiliki prefix /admin
Route::prefix('admin')->group(function () {
    Route::get('/dashboard', [AdminController::class, 'dashboard']); // /admin/dashboard
    Route::get('/users', [AdminController::class, 'users']);         // /admin/users
    Route::resource('/posts', AdminPostController::class);           // /admin/posts/...
});

Group dengan Middleware

// Semua route ini membutuhkan user yang sudah login
Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'show']);
    Route::resource('tasks', TaskController::class);
});

// Middleware ganda
Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
});

Kombinasi Prefix dan Middleware

Route::prefix('admin')
     ->middleware(['auth', 'admin'])
     ->name('admin.')
     ->group(function () {
         Route::get('/dashboard', [AdminController::class, 'index'])->name('dashboard');
         // URL: /admin/dashboard
         // Name: admin.dashboard
     });

Dependency Injection di Controller

Laravel memiliki Service Container yang secara otomatis meng-inject dependency ke controller. Ini sangat berguna untuk Request object.

use Illuminate\Http\Request;

class TaskController extends Controller
{
    public function store(Request $request)
    {
        // $request otomatis di-inject oleh Laravel
        $title = $request->input('title');
        $description = $request->input('description', 'Tidak ada deskripsi');

        // Cek apakah field ada
        if ($request->has('due_date')) {
            $dueDate = $request->input('due_date');
        }

        // Ambil semua input
        $all = $request->all();

        // Ambil hanya beberapa field
        $data = $request->only(['title', 'description']);

        return redirect()->route('tasks.index');
    }
}

Melihat Semua Route

Gunakan Artisan untuk melihat daftar lengkap semua route yang terdaftar:

php artisan route:list

# Filter berdasarkan nama
php artisan route:list --name=tasks

# Filter berdasarkan method
php artisan route:list --method=GET

Output contoh:

  GET    /                          - welcome
  GET    /tasks                     tasks.index   TaskController@index
  GET    /tasks/create              tasks.create  TaskController@create
  POST   /tasks                     tasks.store   TaskController@store
  GET    /tasks/{task}              tasks.show    TaskController@show
  GET    /tasks/{task}/edit         tasks.edit    TaskController@edit
  PUT|PATCH /tasks/{task}           tasks.update  TaskController@update
  DELETE /tasks/{task}              tasks.destroy TaskController@destroy

Troubleshooting: Error yang Sering Muncul

404 Not Found Meski Route Sudah Didefinisikan

Penyebab: Cache route lama masih aktif, atau penulisan URL tidak sesuai.

Solusi:

# Bersihkan cache route
php artisan route:clear
php artisan cache:clear

# Cek apakah route terdaftar
php artisan route:list | grep tasks

MethodNotAllowedHttpException — Method Not Allowed

Penyebab: Form HTML secara default hanya bisa mengirim GET dan POST. Untuk DELETE dan PUT, perlu spoofing menggunakan @method.

Solusi:

{{-- Form untuk DELETE --}}
<form action="{{ route('tasks.destroy', $task->id) }}" method="POST">
    @csrf
    @method('DELETE')  {{-- Ini wajib! --}}
    <button type="submit">Hapus</button>
</form>

{{-- Form untuk PUT (Edit) --}}
<form action="{{ route('tasks.update', $task->id) }}" method="POST">
    @csrf
    @method('PUT')  {{-- Ini wajib! --}}
    ...
</form>

Target class [TaskController] does not exist

Penyebab: Lupa menambahkan use statement atau nama class salah.

Solusi:

<?php
// routes/web.php

// Pastikan menambahkan use statement
use App\Http\Controllers\TaskController;

// Bukan seperti ini (string):
Route::get('/tasks', 'TaskController@index'); // ❌ Laravel 8+ tidak pakai ini

// Tapi seperti ini:
Route::get('/tasks', [TaskController::class, 'index']); // ✅

Pertanyaan yang Sering Diajukan

Apa perbedaan routes/web.php dan routes/api.php?

web.php digunakan untuk halaman web yang memiliki session, cookies, dan CSRF protection — cocok untuk aplikasi web biasa. api.php digunakan untuk endpoint API yang stateless (tanpa session) — cocok untuk aplikasi mobile atau SPA. Kita akan membahas API routing lengkap di artikel REST API dengan Laravel Sanctum.

Kapan menggunakan Route::resource vs route manual?

Gunakan Route::resource jika kamu sedang membangun operasi CRUD standar untuk satu model (Task, Post, Product, dll). Gunakan route manual jika kamu butuh route yang tidak mengikuti pola CRUD, seperti /dashboard, /search, atau /export-pdf.

Apa itu middleware di Laravel?

Middleware adalah filter yang dieksekusi sebelum request sampai ke controller. Contoh: middleware auth akan redirect ke halaman login jika user belum login. Middleware throttle membatasi jumlah request per menit. Kita akan belajar lebih dalam tentang middleware di artikel Authentication di Laravel.


Kesimpulan

Kita sudah menguasai routing dan controller — tulang punggung setiap aplikasi Laravel! Berikut yang sudah kita pelajari:

  • Routing dasar dengan berbagai HTTP method
  • Parameter URL yang wajib dan opsional
  • Named routes untuk URL generation yang fleksibel
  • Controller untuk memisahkan logika dari route
  • Resource Controller yang menghasilkan 7 route CRUD sekaligus
  • Route Group untuk mengorganisir route dengan prefix dan middleware

Di artikel berikutnya, kita masuk ke Blade Template Engine — cara membuat tampilan yang dinamis dan cantik untuk aplikasi Task Manager kita.

Kamu sudah semakin dekat dengan menjadi Laravel developer yang solid. Terus semangat! 🎯

Artikel Terkait