D
P
0

WordPress & PHP

Filter PHP-mu Jalan tapi Halaman Kosong? Tema Tanpa `page.php`/`search.php` Diam-diam Jatuh ke `index.php`

24 Juni 2026·4 menit baca
Filter PHP-mu Jalan tapi Halaman Kosong? Tema Tanpa `page.php`/`search.php` Diam-diam Jatuh ke `index.php`

Gejalanya bikin gemas: halaman hasil pencarian di sebuah custom theme yang saya bangun cuma menampilkan placeholder kosong. Tidak ada error fatal, tidak ada warning di log, tidak ada apa-apa. Cuma area konten yang melompong. Halaman arsip juga sama nasibnya. Padahal saya sudah pasang pre_get_posts untuk menyetel ulang query-nya, dan kalau saya error_log di dalam hook itu, baris log-nya muncul rapi. Filter saya jalan. Tapi layar tetap kosong.

Jadi saya mulai dari asumsi paling jelek: pasti filter saya yang rusak.

add_action( 'pre_get_posts', function ( $query ) {
	if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
		$query->set( 'post_type', 'listing' );
		$query->set( 'posts_per_page', 12 );
		error_log( 'pre_get_posts JALAN untuk search: ' . $query->get( 's' ) );
	}
} );

Log-nya muncul setiap kali saya search. Argumen query masuk. WP_Query yang dihasilkan, ketika saya dump, isinya benar — ada post-nya, found_posts lebih dari nol. Tapi di browser tetap kosong. Saya habis berjam-jam mengutak-atik kondisi is_search(), mencurigai prioritas hook, mengira ada plugin lain yang menimpa query saya. Semuanya buntu, karena saya mendebug bagian yang sebenarnya sudah benar.

Kenapa ini terjadi

Akhirnya saya berhenti memelototi filter dan bertanya hal yang seharusnya saya tanyakan sejak awal: file template mana yang sebenarnya dimuat WordPress untuk halaman ini?

Saya buka folder root tema dan benar-benar melihat daftar isinya. Tidak ada search.php. Tidak ada archive.php. Tidak ada page.php. Tema ini cuma punya index.php, header.php, footer.php, dan functions.php. Dan index.php-nya? Sebuah placeholder telanjang — markup pembungkus, tanpa The Loop yang sesungguhnya.

Di situ langsung jelas. WordPress punya template hierarchy: untuk hasil pencarian dia cari search.php dulu, kalau tidak ada turun ke archive.php, lalu index.php sebagai jaring pengaman paling akhir. Hierarki ini tidak pernah error kalau file-nya hilang — dia diam-diam jatuh ke level berikutnya. Karena tema saya tidak punya search.php maupun archive.php, setiap pencarian dan setiap arsip akhirnya dilayani oleh index.php.

Dan inilah jebakan halusnya: hook saya tetap jalan. pre_get_posts itu menempel ke proses query, bukan ke file template. Jadi main query saya dimodifikasi dengan benar, post-nya diambil dengan benar, found_posts benar — lalu WordPress menyerahkan hasil itu ke index.php, yang tidak punya loop untuk merendernya. Hasilnya tersedia tapi tidak pernah dicetak. Itulah kenapa "filter jalan, halaman kosong" bisa terjadi sekaligus: dua hal itu hidup di pipeline yang berbeda.

Perbaikannya

Diagnosis yang menentukan bukan menambah var_dump, tapi mengkonfirmasi file mana yang benar-benar di-load. Cara tercepat: hook template_include dan log path-nya.

add_filter( 'template_include', function ( $template ) {
	error_log( 'Template yang dimuat: ' . $template );
	return $template;
}, 999 );

Sekali search, log-nya menunjuk hidung: .../themes/custom-theme/index.php. Bukan search.php yang saya kira. (Kalau malas nulis hook, Query Monitor menampilkan template aktif di panel "Template" — informasi yang sama.) Sebelum menyalahkan filter apa pun, langkah pertama saya sekarang adalah ls root tema untuk file template yang diharapkan, lalu konfirmasi mana yang sebenarnya termuat.

Perbaikannya jelas begitu akar masalahnya kelihatan: tambahkan file template yang hilang, masing-masing dengan loop sungguhan. search.php:

<?php get_header(); ?>
 
<main class="search-results">
	<?php if ( have_posts() ) : ?>
		<h1>Hasil untuk "<?php echo esc_html( get_search_query() ); ?>"</h1>
		<?php while ( have_posts() ) : the_post(); ?>
			<article>
				<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
				<?php the_excerpt(); ?>
			</article>
		<?php endwhile; ?>
	<?php else : ?>
		<p>Tidak ada hasil yang cocok.</p>
	<?php endif; ?>
</main>
 
<?php get_footer(); ?>

Saya tambahkan archive.php dan page.php dengan pola yang sama. Refresh — hasil pencarian langsung muncul, semua dengan data yang dari awal sudah disiapkan filter saya. Tidak ada satu baris pun di pre_get_posts yang perlu diubah. Memang tidak pernah salah.

Pelajaran

"Filter saya jalan tapi tidak ada yang muncul" sering kali bukan soal filternya sama sekali — itu sinyal bahwa template hierarchy resolve ke file yang berbeda dari yang kamu kira. Hook bekerja di pipeline query; rendering bekerja di pipeline template. Keduanya bisa benar dan salah secara terpisah.

Jadi sebelum menambah satu var_dump lagi ke logika query, konfirmasi dulu file yang termuat. ls root tema untuk template yang kamu harapkan ada, dan hook template_include (atau buka Query Monitor) untuk melihat yang benar-benar di-load. Tema yang kekurangan page.php, search.php, atau archive.php tidak akan mengeluh — ia akan diam-diam jatuh ke index.php, dan kalau index.php-mu cuma placeholder, kamu akan menghabiskan sore mendebug kode yang dari awal memang sudah benar.