Sebuah controller hidup di antara dua objek besar: Request yang masuk dan response yang keluar. Kita sudah memakai keduanya secara diam-diam — Request hadir sebagai parameter method sejak chapter pertama Section ini, dan setiap return yang kita tulis otomatis dibungkus Laravel menjadi response HTTP. Chapter ini membuat keduanya eksplisit: membaca input dari Request, mengembalikan view untuk halaman HTML, teks polos, response buatan dengan status code dan header kustom, sampai response tanpa isi sama sekali.

Request sebagai Parameter Method #

Objek Request adalah pintu masuk seluruh data dari pengirim: input form, query string, cookie, sampai berkas upload. Kita cukup men-type-hint-nya sebagai parameter method, dan container menyuntikkannya otomatis — mekanisme chapter sebelumnya. Controller berikut membaca query parameter nama dengan nilai bawaan bila tidak dikirim:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;

class SalamController extends Controller
{
    public function sapa(Request $request): View
    {
        $nama = $request->input('nama', 'Tamu');

        return view('salam', ['nama' => $nama]);
    }

    public function salamTeks(): string
    {
        return 'Selamat pagi, semangat belajar Laravel!';
    }

    public function laporan(): Response
    {
        return response()->make(
            'Laporan mingguan selesai disusun.',
            202,
            ['X-Disusun-Oleh' => 'sistem-laporan'],
        );
    }

    public function kosong(): Response
    {
        return response()->noContent();
    }
}

Method input() menerima nama parameter lalu nilai kedua sebagai default — pemakaian $request->input('nama', 'Tamu') menghasilkan Budi untuk ?nama=Budi dan Tamu bila query-nya kosong. Kemampuan Request jauh lebih luas dari sekadar membaca input; kita sudah mengupasnya di chapter Request Object .

Mengembalikan View #

Panggilan view('salam', ['nama' => $nama]) me-render berkas resources/views/salam.blade.php dan meneruskan data kedua sebagai variabel yang bisa dipakai Blade:

blade
<h1>Halo, {{ $nama }}!</h1>
<p>Selamat datang di halaman latihan controller.</p>

Data dapat dikirim dengan dua gaya yang hasilnya identik. Array eksplisit menuliskan nama variabel di sisi view, sedangkan compact() membangun array dari nama variabel lokal:

GayaKodeHasil di view
Array eksplisitview('salam', ['nama' => $nama])$nama
compact()view('salam', compact('nama'))$nama

Array eksplisit lebih tahan salah kaprah saat nama variabel di controller dan di view berbeda; compact() lebih ringkas saat nama variabel sudah sama persis. Apa pun gayanya, data yang dikirim menjadi variabel biasa di dalam Blade — $nama — tanpa prefiks $data atau akses array. Seluruh pembahasan Blade menunggu Section View dan Blade — sekarang kita fokus pada response yang dikembalikan.

Tiga Bentuk Response Lain #

Tiga method terakhir di controller di atas memperlihatkan bentuk response non-view. salamTeks() mengembalikan string polos, laporan() memakai helper response()->make() dengan tiga argumen — isi, status code, dan array header — sedangkan kosong() menghasilkan response 204 tanpa isi. Status 202 dipilih bukan tanpa alasan: Accepted menyatakan request diterima dan sedang diproses, makna yang tepat untuk laporan yang baru disusun dan belum tentu selesai dibaca; setiap status code membawa janji semantik kepada client, dan controller adalah tempat memilihnya. Route untuk keempat method tersebut:

php
<?php

use App\Http\Controllers\SalamController;
use Illuminate\Support\Facades\Route;

Route::get('/sapa', [SalamController::class, 'sapa']);
Route::get('/salam-teks', [SalamController::class, 'salamTeks']);
Route::get('/laporan', [SalamController::class, 'laporan']);
Route::get('/kosong', [SalamController::class, 'kosong']);

Kita uji keempatnya sekaligus dengan pola runner uji-route.php yang sudah biasa kita pakai, kali ini juga mencetak header penting dari tiap response:

php
<?php

// uji-response.php — jalankan dari root proyek Laravel
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

$dir = $argv[1];
require $dir.'/vendor/autoload.php';
$app = require $dir.'/bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$permintaan = [
    ['GET', '/sapa?nama=Budi'],
    ['GET', '/salam-teks'],
    ['GET', '/laporan'],
    ['GET', '/kosong'],
];

foreach ($permintaan as [$method, $uri]) {
    $response = $kernel->handle(
        Request::create('http://localhost:8000'.$uri, $method)
    );
    echo str_pad("{$method} {$uri}", 26)
        ." → HTTP ".$response->getStatusCode().PHP_EOL;

    foreach (['Content-Type', 'X-Disusun-Oleh'] as $header) {
        $nilai = $response->headers->get($header);
        if ($nilai) {
            echo str_pad('', 26)."   {$header}: {$nilai}".PHP_EOL;
        }
    }
}

Output yang Dihasilkan:

text
GET /sapa?nama=Budi        → HTTP 200
                             Content-Type: text/html; charset=utf-8
GET /salam-teks            → HTTP 200
                             Content-Type: text/html; charset=utf-8
GET /laporan               → HTTP 202
                             Content-Type: text/html; charset=utf-8
                             X-Disusun-Oleh: sistem-laporan
GET /kosong                → HTTP 204

Empat baris tersebut merangkum perilaku response Laravel. String dan hasil make() sama-sama dijawab 200 dengan Content-Type: text/html — kecuali kita mengubahnya; status 202 pada /laporan berasal langsung dari argumen kedua make(); header kustom X-Disusun-Oleh ikut terkirim apa adanya; dan noContent() menghasilkan 204, status khusus yang menyatakan sukses tanpa isi. Response kosong seperti ini lazim untuk endpoint DELETE dan operasi yang cukup diberitahu berhasilnya tanpa perlu mengirim data kembali.

Satu bentuk response penting belum muncul: pengalihan halaman. Setelah form disimpan, keputusan paling umum bukan menampilkan halaman baru, melainkan memindahkan pengguna ke halaman lain — topik chapter Redirect dan Response berikutnya.