Sebuah situs klien yang saya bangun ulang pakai block theme (FSE) punya masalah aneh di halaman kontak. Saya baru saja menambahkan dua pattern baru, contact-hero dan contact-layout, sebagai file di dalam folder patterns/ tema. Buka editor, harusnya keduanya nongol di daftar pattern. Tapi tidak. Yang muncul cuma dua pattern lama yang sudah ada dari kemarin, coverage-regions dan shield-ready. Dua yang baru? Lenyap. Bukan error, bukan warning, cuma tidak ada.
Yang bikin pusing: file-nya jelas ada di disk. Header comment-nya benar. Slug-nya unik. Kalau saya salah nulis, minimal ada notice atau pattern-nya muncul dalam kondisi rusak. Ini beda: WordPress berperilaku seolah file itu tidak pernah ada. Halaman kontak yang saya rakit dari empat pattern akhirnya render cuma dengan dua, dan dua slot baru itu diam-diam kosong. Tidak ada jejak di error_log, tidak ada apa-apa.
Gejalanya
Reaksi pertama saya: pasti ada yang salah di file pattern-nya. Saya banding-bandingkan header dua file baru dengan dua file lama yang jalan. Baris Title:, Slug:, dan Categories: sama persis polanya. Saya rename slug-nya, saya pangkas markup-nya jadi satu <!-- wp:paragraph --> polos buat memastikan bukan blok tertentu yang gagal parse. Tetap tidak muncul.
Lalu saya curiga cache biasa. Purge object cache, restart PHP, hard refresh editor. Nihil. Saya bahkan sempat mikir ini soal permission file atau opcache PHP yang memegang versi lama di memori. Saya jalankan opcache_reset(). Masih dua pattern.
Yang akhirnya membelokkan penyelidikan: pattern lama muncul, pattern baru tidak. Kalau registrasi pattern total mati, keduanya pasti hilang. Tapi ini selektif: yang lama ada, yang baru diabaikan. Itu bukan pola bug parsing. Itu pola sebuah cache yang isinya beku sejak dua pattern lama pertama kali didaftarkan.
Menelusuri akar masalah
Di block theme, WordPress mendaftarkan pattern dari folder patterns/ secara otomatis. Yang jarang orang tahu: hasil scan folder itu tidak dibaca ulang tiap request. WordPress menyimpan seluruh daftar pattern di sebuah site-transient bernama wp_theme_files_patterns-{md5(stylesheet_dir)}, dengan masa hidup satu minggu.
Isi transient itu bukan cuma daftar pattern, tapi juga field version yang mencatat versi tema saat cache ditulis. Waktu WordPress mau membacanya, dia bandingkan version di cache dengan Version di style.css. Kalau sama, dia pakai cache apa adanya dan tidak repot-repot scan folder patterns/ lagi. Artinya: selama versi tema tidak berubah, menambah file patterns/*.php baru sama sekali tidak terdeteksi sampai transient-nya kedaluwarsa sendiri, satu minggu kemudian.
Itu persis kejadiannya. Dua pattern lama masuk ke cache waktu transient pertama kali ditulis. Saya menambah dua file baru tanpa menyentuh nomor versi tema, jadi WordPress terus menyajikan snapshot lama yang cuma berisi dua pattern. Bukan file-nya yang salah, bukan editor yang rusak. Daftar pattern-nya di-cache, dan saya tidak dapat sinyal apa pun karena ini transient, bukan sesuatu yang muncul di UI.
Perbaikannya
Ada dua cara, dan keduanya benar.
Cara cepat manual: naikkan Version di style.css setiap kali menambah pattern. Perubahan versi bikin version di cache tidak cocok, jadi WordPress buang cache lalu scan ulang.
/*
Theme Name: Situs Klien
Version: 1.4.2
*/Tapi mengandalkan ingatan buat bump versi tiap nambah pattern itu rapuh. Cara yang saya pasang permanen: satu guard kecil di inc/patterns.php, di-hook ke init dengan prioritas 1 (sebelum WordPress sempat membaca cache pattern), yang membandingkan mtime tiap file pattern dengan waktu cache ditulis. Kalau ada file yang lebih baru dari cache, hapus transient-nya.
add_action( 'init', function () {
$dir = get_stylesheet_directory();
$key = 'wp_theme_files_patterns-' . md5( $dir );
// Site transient menyimpan waktu kedaluwarsanya di sebuah option.
$timeout = (int) get_site_option( '_site_transient_timeout_' . $key );
if ( ! $timeout ) {
return; // belum ada cache, biar WordPress yang bangun.
}
$written_at = $timeout - WEEK_IN_SECONDS;
// Ada file pattern yang lebih baru dari cache?
$newest = 0;
foreach ( glob( $dir . '/patterns/*.php' ) as $file ) {
$newest = max( $newest, filemtime( $file ) );
}
if ( $newest > $written_at ) {
delete_site_transient( $key );
}
}, 1 );Karena site transient itu hidup satu minggu, waktu tulisnya bisa dihitung mundur: timeout dikurangi WEEK_IN_SECONDS. Begitu ada file pattern yang mtime-nya lebih baru dari itu, transient dihapus, dan WordPress terpaksa scan folder patterns/ lagi di request yang sama. Pattern baru langsung muncul, tanpa saya harus ingat apa-apa.
Untuk mesin development, ada jalan ketiga yang lebih bersih: aktifkan development mode WordPress. Dengan define( 'WP_DEVELOPMENT_MODE', 'all' ); (atau 'theme') di wp-config.php, WordPress melewati cache pattern sepenuhnya, jadi tiap perubahan file langsung kelihatan. Saya pakai ini di lokal, dan guard mtime di atas buat produksi.
Checklist
- Kalau pattern baru di block theme tidak muncul tapi yang lama tetap ada, curigai cache daftar pattern, bukan file-nya.
- Daftar pattern di-cache di site-transient
wp_theme_files_patterns-{md5(stylesheet_dir)}selama satu minggu. - WordPress cuma invalidasi cache ini saat
Versiondistyle.cssberubah, bukan saat kamu menambah filepatterns/*.php. - Perbaikan manual paling cepat: bump
Versiontema tiap menambah pattern. - Perbaikan permanen: guard di
initprioritas 1 yang membandingkanfilemtime()tiap file pattern dengan waktu tulis cache, laludelete_site_transient()kalau ada yang lebih baru. - Di lokal, set
WP_DEVELOPMENT_MODEkethemeatauallsupaya cache pattern dilewati sepenuhnya.
