Membuat controller dengan artisan, memahami resource controllers dan dependency injection, memvalidasi input lewat $request->validate(), memindahkan logika validasi ke Form Request classes, serta urutan middleware pada request lifecycle.

Setelah di episode 4 kita memetakan URL lewat routing, sekarang kita isi "otak" aplikasi: controller. Di episode 2 kita belajar bahwa controller adalah jembatan antara request, model, dan view. Di episode ini kita praktikkan secara penuh — termasuk bagaimana Laravel menyuntikkan dependensi otomatis (dependency injection) dan bagaimana request divalidasi dengan benar.
Controller yang ditulis dengan pola yang baik adalah fondasi aplikasi yang mudah diuji dan dipelihara. Mari mulai dari yang paling dasar.
php artisan make:controller PostControllerPerintah di atas membuat app/Http/Controllers/PostController.php. Isinya kosong, siap kita isi:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
return view('posts.index');
}
}Hubungkan ke route di episode 4 — Route::get('/posts', [PostController::class, 'index']) — dan controller sudah aktif. Perhatikan type hint Request $request pada parameter: inilah dependency injection yang dijanjikan. Laravel melihat type hint, membuat instance Request dari container, dan menyuntikkannya otomatis. Kalian tidak pernah membuat request manual.
Untuk CRUD standar, Laravel menyediakan controller siap-pakai dengan 7 method: index, create, store, show, edit, update, destroy:
php artisan make:controller PostController --resourceRoute-nya cukup satu baris:
Route::resource('posts', PostController::class);Satu baris ini menghasilkan 7 route sekaligus (termasuk named routes posts.index, posts.store, dan seterusnya). Cek dengan php artisan route:list untuk melihat semuanya. Untuk API yang hanya butuh index, store, show, update, destroy, gunakan --api:
php artisan make:controller PostController --apiContainer menyuntikkan tidak hanya Request, tapi juga service apa pun yang dibutuhkan:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use App\Services\PostService;
class PostController extends Controller
{
public function __construct(
protected PostService $posts,
) {
}
public function show(Post $post)
{
return view('posts.show', ['post' => $post]);
}
}Di sini ada dua hal: PostService di constructor (disuntikkan otomatis oleh container) dan route model binding Post $post — Laravel membaca parameter {post} dari URL, mencari Post dengan id tersebut di database, dan menyuntikkan instance-nya. Jika tidak ditemukan, otomatis 404. Tidak perlu query manual.
Validasi server-side adalah garis pertahanan utama aplikasi web. Cara paling sederhana:
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'body' => 'required|string',
'status' => 'in:draft,published',
]);
Post::create($validated);
return redirect()->route('posts.index');
}$request->validate() mengembalikan data yang sudah lolos. Jika gagal, Laravel otomatis me-redirect balik ke halaman sebelumnya dengan error di session — siap ditampilkan di Blade memakai @error. Aturan bisa ditulis dengan pipe (required|max:255) atau array (['required', 'string', 'max:255']) — array lebih mudah dibaca.
Note
Peraturan validasi Laravel sangat kaya: email, unique:users,email, exists:posts,id, date, min:8, confirmed, image, file, dan puluhan lainnya. Semuanya kita bedah lebih dalam di episode 12 bersama custom rules.
Jika validasi mulai panjang atau dipakai di beberapa tempat, pindahkan ke Form Request — class khusus yang merangkum aturan dan logika otorisasi:
php artisan make:request StorePostRequest<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
];
}
}Controller menjadi sangat bersih — cukup type hint Form Request:
public function store(StorePostRequest $request)
{
Post::create($request->validated());
return redirect()->route('posts.index');
}authorize() juga bisa mengecek izin user di sini — jika false, Laravel mengembalikan 403. Kita akan mengkombinasikannya dengan Gates & Policies di episode 11.
Di episode 2 kita tahu middleware dieksekusi sebelum controller. Urutan lengkap untuk request masuk adalah: global middleware (semua route) → group middleware (web/api) → route middleware. Untuk form di aplikasi web, web group membawa session, CSRF, dan cookie encryption — inilah mengapa form POST selalu butuh token @csrf (detail di episode 16).
Jika ingin melihat middleware yang aktif pada sebuah request, tambahkan middleware bernama di route:
Route::post('/posts', [PostController::class, 'store'])
->middleware('auth');Inti yang harus dibawa pulang:
php artisan make:controller; gunakan --resource untuk CRUD.Request, service, dan model secara otomatis.$request->validate(); pindahkan ke Form Request saat mulai kompleks.Di episode 6 selanjutnya kita akan membahas Blade templating — @extends, @section, @include, sintaks {{ }} yang auto-escaped, loop & kondisional, serta komponen Blade (x-) untuk layout yang reusable. Sampai jumpa di episode 6!