Saya sedang membangun block theme FSE untuk sebuah situs company profile, dan pekerjaannya sesederhana mungkin: pasang logo brand di header. Buka parts/header.html, tulis tag img, isi src-nya dengan helper yang sudah saya pakai ribuan kali di tema klasik. Refresh. Logonya rusak.
Gejalanya: yang keluar bukan URL, tapi kodenya
Ikon gambar rusak di pojok kiri atas. Refleks pertama saya seperti biasa salah sasaran: saya kira nama filenya salah ketik, atau file webp-nya belum ke-upload, atau ada salah huruf besar-kecil di nama folder. Saya cek disk, filenya ada. Saya buka URL asetnya langsung di browser, gambarnya tampil normal.
Baru setelah itu saya buka View Source, dan jawabannya sudah menunggu di sana dalam bentuk paling telanjang:
<img src="<?php echo esc_url(get_template_directory_uri()); ?>/assets/img/logo/logo-transparent_w480.webp" alt="Logo">Itu bukan hasil render. Itu kode saya, dikirim mentah-mentah ke browser sebagai teks. Browser jelas menganggapnya sebagai path relatif yang aneh, gagal mengambilnya, dan menampilkan ikon rusak. Tidak ada error PHP, tidak ada warning, tidak ada baris apa pun di error_log. Dari sisi WordPress, tidak ada yang salah, karena memang tidak ada yang dieksekusi.
Akar masalahnya: parts/ dan templates/ itu HTML, bukan PHP
Ini bagian yang butuh waktu untuk saya terima, karena bertentangan dengan refleks bertahun-tahun bikin tema klasik.
Di block theme FSE, file di dalam parts/ dan templates/ berekstensi .html bukan karena konvensi penamaan yang manis. Ekstensi itu jujur. File-file tersebut memang file HTML statis. WordPress membacanya sebagai markup blok, bukan sebagai template yang perlu diproses PHP. Tidak ada tahap parsing PHP di jalur itu sama sekali, jadi apa pun yang berbentuk <?php ... ?> diperlakukan sebagai teks biasa dan ikut tercetak ke output.
Yang membuat ini makin membingungkan: di dalam tema yang sama, PHP jalan di tempat lain. File di patterns/*.php mengeksekusi PHP dengan normal. Saya sempat berasumsi kalau satu bagian tema bisa menjalankan PHP, maka bagian lain juga bisa, dan asumsi itu yang bikin saya membuang waktu mencari salah ketik.
Perbedaannya ada di cara keduanya dimuat. Pattern didaftarkan lewat mekanisme registrasi pattern WordPress yang menjalankan file PHP-nya dan menangkap outputnya, jadi kode di dalamnya benar-benar dieksekusi seperti file PHP biasa. Template part dan template tidak lewat jalur itu. Isinya diambil sebagai konten blok apa adanya.
Dan ini berlaku untuk semua PHP, bukan cuma helper URL. Kalau kamu menaruh wp_nonce_field() di parts/header.html, yang keluar adalah teks wp_nonce_field(). Kondisional if juga tidak akan dievaluasi, dia hanya jadi tulisan. Tidak ada pengecualian yang perlu kamu hafal, karena tidak ada eksekusi sama sekali.
Perbaikannya
Ada tiga jalan, tergantung apa yang sebenarnya kamu butuhkan.
Pertama, dan paling sering ini yang tepat: pakai path web absolut. Kalau yang kamu butuhkan cuma URL aset di dalam tema, kamu tidak butuh PHP untuk itu. Path tema sudah kamu ketahui saat menulis:
<img src="/wp-content/themes/nama-tema/assets/img/logo/logo-transparent_w480.webp" alt="Logo">Kelihatannya kurang "benar" dibanding memanggil helper, tapi di dalam parts/ dan templates/ inilah satu-satunya bentuk yang jalan. Path ini hardcoded relatif terhadap root situs, dan untuk instalasi satu situs dengan direktori tema standar, dia stabil.
Kedua, pindahkan markup-nya ke pattern kalau memang butuh PHP. Di patterns/*.php, helper yang tadi gagal jalan mulus:
<img src="<?php echo esc_url( get_template_directory_uri() ); ?>/assets/img/logo/logo-transparent_w480.webp" alt="Logo">Jadi kalau ada bagian header yang benar-benar butuh logika PHP, potong bagian itu jadi pattern, lalu sisipkan pattern-nya dari template part.
Ketiga, kalau path-nya harus dinamis, pakai blok inti. Untuk kasus logo, core/site-logo adalah jawaban yang paling aman. Blok itu dirender WordPress sendiri dan URL-nya diselesaikan mengikuti instalasi, jadi dia tetap benar walaupun WordPress dipasang di subdirektori atau direktori konten dipindah dari lokasi standarnya. Di kondisi seperti itulah path absolut hardcoded tadi mulai patah. Satu catatan: logo yang dipakai blok ini diambil dari pengaturan situs, bukan dari folder tema, jadi file logonya harus kamu unggah ke media library dulu.
Yang saya bawa pulang
- Ekstensi file di block theme itu bukan gaya-gayaan.
.htmldiparts/dantemplates/artinya file itu benar-benar diperlakukan sebagai HTML statis, tanpa tahap PHP. - PHP yang tidak dieksekusi tidak menghasilkan error, dia menghasilkan teks. Jadi kalau ada bagian halaman yang terlihat "rusak biasa", buka View Source sebelum menuduh path atau nama file.
- Dalam satu tema,
patterns/*.phpmenjalankan PHP tapiparts/dantemplates/tidak. Jangan generalisasi dari satu folder ke folder lain. - Untuk aset di dalam tema, path web absolut sudah cukup. Untuk yang benar-benar dinamis, blok inti yang dirender WordPress lebih tahan banting daripada string yang kamu tulis sendiri.