Chapter sebelumnya menunjukkan bahwa satu route adalah pasangan HTTP method dan URI yang menunjuk satu handler. Dalam praktiknya, aplikasi kita membutuhkan banyak route dengan beragam method: halaman dibaca dengan GET, form dikirim dengan POST, data diubah dengan PUT atau PATCH, dan dihapus dengan DELETE. Chapter ini membahas seluruh method tersebut satu per satu, cara menunjuk route ke controller, jenis response yang bisa dikembalikan handler, serta shortcut untuk view, redirect, dan route fallback. Semua contoh diuji langsung pada aplikasi Laravel 13.
Method HTTP dan Semantiknya #
Setiap HTTP method membawa makna yang disepakati secara luas, dan router Laravel menyediakan satu method pendaftaran untuk masing-masing. Tabel berikut merangkum semantik standarnya:
| Method | Makna | Idempoten | Pemakaian umum |
|---|---|---|---|
GET | membaca data | ya | halaman, daftar, hasil pencarian |
POST | membuat data baru | tidak | submit form, penyimpanan |
PUT | mengganti seluruh resource | ya | update menyeluruh |
PATCH | mengubah sebagian resource | ya | update sebagian |
DELETE | menghapus resource | ya | penghapusan |
OPTIONS | menanyakan method yang tersedia | ya | preflight request CORS |
Kolom idempoten berarti request yang sama boleh diulang berkali-kali tanpa mengubah hasil akhir — DELETE /tugas yang dijalankan dua kali tetap berakhir pada kondisi yang sama: tugasnya hilang. Semantik ini bukan sekadar gaya penulisan: HTTP client, cache, dan proxy memakainya untuk mengambil keputusan.
Menulis Route untuk Setiap Method #
Kita bangun endpoint /tugas lengkap dengan lima method utama, plus satu route OPTIONS yang biasa dipakai browser untuk pra-penerbangan CORS. Buat terlebih dahulu controller-nya dengan php artisan make:controller TugasController, lalu isi app/Http/Controllers/TugasController.php:
<?php
namespace App\Http\Controllers;
class TugasController extends Controller
{
// GET /tugas — daftar seluruh tugas
public function index()
{
return response()->json([
['id' => 1, 'judul' => 'Belajar routing Laravel'],
['id' => 2, 'judul' => 'Kirim laporan mingguan'],
]);
}
// POST /tugas — simpan tugas baru
public function simpan()
{
return response()->json(['status' => 'tersimpan'], 201);
}
// PUT /tugas — perbarui kumpulan tugas
public function perbarui()
{
return response()->json(['status' => 'diperbarui']);
}
// PATCH /tugas — tandai selesai sebagian
public function tandaiSelesai()
{
return response()->json(['status' => 'selesai']);
}
// DELETE /tugas — hapus tugas
public function hapus()
{
return response()->noContent();
}
}Selanjutnya daftarkan route-nya di routes/web.php. Handler ditulis dalam bentuk array [NamaController::class, 'method'] — bentuk alternatif dari closure yang kita pakai di chapter sebelumnya:
<?php
use App\Http\Controllers\TugasController;
use Illuminate\Support\Facades\Route;
// Route paling sederhana: closure mengembalikan string
Route::get('/halo', function () {
return 'Halo, Laravel!';
});
// Route yang menunjuk ke method controller
Route::get('/tugas', [TugasController::class, 'index']);
Route::post('/tugas', [TugasController::class, 'simpan']);
Route::put('/tugas', [TugasController::class, 'perbarui']);
Route::patch('/tugas', [TugasController::class, 'tandaiSelesai']);
Route::delete('/tugas', [TugasController::class, 'hapus']);
Route::options('/tugas', function () {
return response()->noContent();
});Perintah route:list memperlihatkan keenam route tersebut terdaftar rapi di URI yang sama namun method berbeda:
php artisan route:list --except-vendor --path=tugasOutput yang Dihasilkan:
ANY daftar-tugas ................................. Illuminate\Routing › RedirectController
GET|HEAD tugas .......................................................... TugasController@index
POST tugas ......................................................... TugasController@simpan
PUT tugas ....................................................... TugasController@perbarui
PATCH tugas .................................................. TugasController@tandaiSelesai
DELETE tugas .......................................................... TugasController@hapus
OPTIONS tugas .............................................................. routes/web.php:17
Showing [7] routesDua hal menarik dari output di atas. Filter --path=tugas menyaring URI yang mengandung teks tugas, sehingga route /daftar-tugas ikut tampil. Kolom method pada baris pertama menunjukkan ANY karena route redirect merespons semua method — kita bahas redirect beberapa paragraf ke bawah.
Shortcut view, redirect, dan fallback #
Laravel menyediakan tiga shortcut untuk kasus yang sangat sering muncul. Route::view() langsung mengembalikan sebuah view tanpa closure, Route::redirect() memindahkan request lama ke URI baru dengan status 302, dan Route::fallback() menjadi handler terakhir saat tidak ada route yang cocok. Tambahkan baris berikut ke routes/web.php:
Route::view('/selamat', 'selamat', ['nama' => 'Budi']);
Route::redirect('/daftar-tugas', '/tugas');
Route::permanentRedirect('/tasks', '/tugas');
Route::fallback(function () {
return 'Maaf, halaman yang Anda cari tidak ditemukan.';
});Shortcut Route::view('/selamat', 'selamat', ...) me-render berkas resources/views/selamat.blade.php dan meneruskan data nama, sehingga Blade <h1>Selamat datang, {{ $nama }}!</h1> di dalamnya menampilkan heading “Selamat datang, Budi!”. Route::permanentRedirect() berbeda dari Route::redirect() pada status code-nya: 301 memberi tahu browser dan mesin pencari bahwa perpindahan bersifat permanen, sedangkan 302 bersifat sementara. Kita jalankan skrip uji kecil dari chapter sebelumnya terhadap URI-URI tersebut:
<?php
// uji-route.php — jalankan dari root proyek Laravel
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
require __DIR__.'/vendor/autoload.php';
$app = require __DIR__.'/bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$permintaan = [
['GET', '/halo'],
['GET', '/tugas'],
['GET', '/daftar-tugas'],
['GET', '/tasks'],
['GET', '/tidak-ada'],
];
foreach ($permintaan as [$method, $uri]) {
$response = $kernel->handle(
Request::create('http://localhost:8000'.$uri, $method)
);
$isi = $response->headers->get('Location') ?? trim($response->getContent());
echo str_pad("{$method} {$uri}", 18)
." → HTTP ".$response->getStatusCode()
.' | '.mb_substr($isi, 0, 90).PHP_EOL;
}Output yang Dihasilkan:
GET /halo → HTTP 200 | Halo, Laravel!
GET /tugas → HTTP 200 | [{"id":1,"judul":"Belajar routing Laravel"},{"id":2,"judul":"Kirim laporan mingguan"}]
GET /daftar-tugas → HTTP 302 | /tugas
GET /tasks → HTTP 301 | /tugas
GET /tidak-ada → HTTP 200 | Maaf, halaman yang Anda cari tidak ditemukan.Output tersebut memperlihatkan tiga jenis response sekaligus: teks biasa dari closure /halo, JSON dari response()->json() di TugasController@index, dan redirect 302/301 beserta URI tujuannya di header Location. Baris terakhir menunjukkan fallback bekerja untuk URI tak dikenal.
Menguji Route dengan Feature Test #
Method tulis seperti POST dan DELETE tidak bisa diuji dengan skrip runner begitu saja, karena route di routes/web.php dilindungi middleware ValidateCsrfToken — request tulis tanpa token CSRF akan dijawab 419 Page Expired (perilaku ini sudah kita verifikasi langsung). Cara paling praktis menguji route tulis adalah feature test, karena environment testing membuat middleware CSRF membiarkan request lewat. Buat tests/Feature/TugasRouteTest.php:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class TugasRouteTest extends TestCase
{
public function test_daftar_tugas_mengembalikan_json(): void
{
$response = $this->get('/tugas');
$response->assertStatus(200);
$response->assertJson([
['id' => 1, 'judul' => 'Belajar routing Laravel'],
]);
}
public function test_simpan_tugas_mengembalikan_201(): void
{
$response = $this->post('/tugas');
$response->assertStatus(201);
$response->assertJson(['status' => 'tersimpan']);
}
public function test_tandai_selesai_mengembalikan_200(): void
{
$response = $this->patch('/tugas');
$response->assertStatus(200);
}
public function test_hapus_tugas_mengembalikan_204(): void
{
$response = $this->delete('/tugas');
$response->assertNoContent();
}
}Lalu jalankan berkas test tersebut:
php artisan test tests/Feature/TugasRouteTest.phpOutput yang Dihasilkan:
PASS Tests\Feature\TugasRouteTest
✓ daftar tugas mengembalikan json
✓ simpan tugas mengembalikan 201
✓ tandai selesai mengembalikan 200
✓ hapus tugas mengembalikan 204
Tests: 4 passed (9 assertions)Keempat test hijau membuktikan seluruh route tulis berfungsi: POST menghasilkan 201, PATCH menghasilkan 200, dan DELETE menghasilkan 204 tanpa konten. Kita akan membedah fitur pengujian Laravel jauh lebih dalam di Section Testing Laravel
; untuk sekarang, pola $this->get()/$this->post() plus assertStatus() sudah cukup untuk memverifikasi route.
Satu hal masih mengganjal: route /tugas kita selalu mengembalikan daftar yang sama, sementara aplikasi nyata perlu menampilkan tugas tertentu — tugas nomor 5, milik pengguna tertentu, pada kategori tertentu. Kebutuhan itulah yang diselesaikan oleh route parameters
, topik chapter berikutnya.