Pesan error bawaan Laravel memang akurat, tetapi ditulis dalam bahasa Inggris dengan gaya teknis: “The judul field must be at least 5 characters.” Untuk aplikasi berbahasa Indonesia, kalimat semacam itu terasa dingin di hadapan pengguna akhir — apalagi nama field seperti kode_promo tampil mentah apa adanya. Laravel menyediakan tiga lapisan kustomisasi pesan: per rule di class FormRequest, penggantian nama attribute, dan file bahasa yang mengubah seluruh pesan bawaan sekaligus. Chapter ini membedah ketiganya secara berurutan, masing-masing dengan hasil nyatanya.
messages(): Pesan per Field dan Rule #
Method messages() pada FormRequest menerima array dengan key berformat field.rule dan nilai berupa teks penggantinya:
class StorePostCustomRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'judul' => ['required', 'string', 'min:5'],
'isi' => ['required', 'string'],
'email' => ['required', 'email'],
];
}
public function messages(): array
{
return [
'judul.required' => 'Judul tulisan wajib diisi.',
'judul.min' => 'Judul minimal :min karakter.',
'email.required' => 'Alamat email wajib diisi.',
'email.email' => 'Format :attribute tidak valid.',
];
}
}Perhatikan dua placeholder di dalam pesan: :min akan diganti nilai parameter rule, dan :attribute diganti nama field. Key yang tidak kita sentuh — misalnya isi.required — tetap memakai pesan bawaan. Kita uji dengan request yang gagal di tiga field sekaligus:
$response = $this->postJson('/custom/posts', [
'judul' => 'abc',
'isi' => '',
'email' => 'bukan-email',
]);Output yang Dihasilkan:
{"message":"Judul minimal 5 karakter. (and 2 more errors)","errors":{"judul":["Judul minimal 5 karakter."],"isi":["The isi field is required."],"email":["Format :attribute tidak valid."]}}Hasilnya sangat informatif: judul tampil dengan pesan buatan kita dan :min terisi angka 5, isi jatuh ke pesan bawaan Inggris, dan pesan email.email masih menampilkan :attribute mentah karena — akan kita rapikan segera — attributes() belum diisi.
attributes(): Nama Field yang Ramah #
Method attributes() memetakan nama field teknis ke label yang manusiawi. Placeholder :attribute di pesan mana pun — termasuk pesan bawaan — akan memakai pemetaan ini:
public function attributes(): array
{
return [
'judul' => 'judul tulisan',
'email' => 'alamat email',
];
}Dengan penambahan tersebut, request yang sama menghasilkan:
Output yang Dihasilkan:
{"message":"Judul minimal 5 karakter. (and 2 more errors)","errors":{"judul":["Judul minimal 5 karakter."],"isi":["The isi field is required."],"email":["Format alamat email tidak valid."]}}Pesan terakhir kini berbunyi Format alamat email tidak valid. — :attribute tergantikan oleh nilai dari attributes(). Perubahan ini juga berlaku untuk semua pesan bawaan lain yang menyebut nama field.
Inline di Controller: Argumen Tambahan validate() #
Jika validasi masih ditulis inline di controller, kedua kustomisasi itu tersedia sebagai argumen kedua dan ketiga validate():
$validated = $request->validate(
[
'nama' => ['required', 'string'],
'email' => ['required', 'email'],
],
[
'nama.required' => 'Nama lengkap wajib diisi.',
'email.email' => ':Attribute harus berformat email yang benar.',
],
[
'nama' => 'nama lengkap',
],
);Argumen kedua adalah array messages, argumen ketiga array attributes — isinya persis seperti method di FormRequest. Placeholder :Attribute dengan huruf kapital di depan otomatis mengkapitalkan huruf pertama hasilnya:
Output yang Dihasilkan:
{"message":"Nama lengkap wajib diisi. (and 1 more error)","errors":{"nama":["Nama lengkap wajib diisi."],"email":["Email harus berformat email yang benar."]}}File Bahasa: Mengubah Pesan Secara Global #
Untuk mengganti pesan di seluruh aplikasi, kita perlu menerbitkan file bahasa Laravel terlebih dahulu:
php artisan lang:publishOutput yang Dihasilkan:
INFO Language files published successfully. Perintah ini membuat direktori lang/en/ berisi validation.php, auth.php, pagination.php, dan passwords.php. Isi lang/en/validation.php adalah array raksasa yang memetakan setiap rule ke teks pesannya:
return [
// ...
'required' => 'The :attribute field is required.',
'email' => 'The :attribute field must be a valid email address.',
'min' => [
'string' => 'The :attribute field must be at least :min characters.',
// ...
],
// ...
];Mengubah satu baris di berkas ini mengubah pesan di seluruh aplikasi. Sebagai contoh, kita ganti baris 'required' menjadi 'Kolom :attribute wajib diisi.' lalu kirim request dengan isi kosong:
Output yang Dihasilkan:
{"message":"Kolom isi wajib diisi.","errors":{"isi":["Kolom isi wajib diisi."]}}File bahasa juga mendukung dua seksi khusus di bagian bawahnya. Seksi custom mengganti pesan untuk kombinasi field dan rule tertentu tanpa menyentuh messages():
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
'isi' => [
'required' => 'Isi tulisan tidak boleh kosong ya.',
],
],Dengan entri 'isi' => ['required' => 'Isi tulisan tidak boleh kosong ya.'] diaktifkan, request dengan isi kosong menghasilkan {"message":"Isi tulisan tidak boleh kosong ya.",...}. Sementara seksi 'attributes' => [] yang masih kosong berfungsi persis seperti method attributes() — tempat mendefinisikan nama ramah untuk seluruh aplikasi. Untuk aplikasi berbahasa Indonesia penuh, kita bisa menyalin direktori lang/en menjadi lang/id dan mengatur APP_LOCALE=id.
Dengan pesan error yang sudah berbahasa manusia, tugas berikutnya adalah menampilkannya di halaman form dengan rapi — mulai dari ringkasan semua error sampai penandaan field yang bermasalah. Itulah pembahasan chapter Error Messages di Blade . Rujukan resminya ada di dokumentasi Validation — Custom Messages .