Mengapa saya harus meletakkan if (have_posts ()), sementara (have_posts ()) tidak cukup?

22

Saya punya pertanyaan tentang "loop".

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>

Kode diambil dari halaman The Loop WordPress Codex .

Mengapa saya harus ikut ifserta? Sepertinya jika ada whileloop, berfungsi dengan baik.

Dalam kasus apa masalah terjadi jika tidak ada ifpernyataan?

Edit

Saya menerima jawaban @ Chip. tapi jujur ​​mengatakan aku hanya butuh bagian terakhir.

Saya tahu sekarang apa yang ingin saya ketahui dari pertanyaan saya.

ifpernyataan hanya bila diperlukan, jika Anda ingin meletakkan header atau footer yang harus ditulis hanya sekali. jika Anda tidak menggunakan "bungkus", maka ifpernyataan itu tidak perlu.

pasir besi
sumber
2
Saya memberikan suara sebelum membaca konten_ the_, judulnya pasti!
brasofilo
Suntingan (final) yang luar biasa. Kebanyakan orang menggunakan jika dan sementara secara langsung setelah satu sama lain tanpa pernah menggunakan yang lain. Kemungkinan karena copy & paste.
Herbert Van-Vliet

Jawaban:

29

Pemuat template WordPress akan menyertakan file templat kontekstual yang sesuai dalam banyak keadaan, bahkan jika kueri untuk konteks itu tidak mengembalikan tulisan. Sebagai contoh:

  • Indeks Posting Blog Utama
  • Indeks Arsip Kategori (Kategori ada, tetapi tidak memiliki pos)
  • Indeks Arsip Tag (Tag ada, tetapi tidak memiliki posting)
  • Indeks Arsip Penulis (Penulis ada, tetapi tidak memiliki posting)
  • Indeks Hasil Pencarian

Dengan demikian, dalam kasus ini, file template yang sesuai akan dimuat, tetapi tidak ada posting yang akan dihasilkan, karena permintaan tidak mengembalikan posting.

Contoh bukti konsep:

Jadi, dalam konteks ini, berguna untuk file templat untuk memasukkan if ( have_posts() )kondisi.

Dalam konteks lain, file template tidak akan pernah dimuat jika permintaan tidak mengembalikan tulisan. Sebagai contoh:

  • Posting blog tunggal
  • Halaman statis

Dalam konteks ini, if ( have_posts() )mungkin tidak perlu.

Edit

Saya mengerti permintaan dipanggil oleh the_post (), kan? Dan jika sementara (have_posts ()) ada, permintaan tidak pernah terjadi jika tidak ada posting.

Untuk memahami apa yang terjadi, Anda harus melihat urutan tindakan WordPress . Dimulai dengan wp_loaded(dan menghilangkan beberapa untuk kejelasan):

  • wp_loaded
  • parse_request
  • send_headers
  • parse_query
  • pre_get_posts
  • wp
  • template_redirect
  • get_header
  • wp_head
  • the_post
  • wp_footer

Jadi, apa yang terjadi, dan dalam urutan apa?

  • Permintaan dipanggil:
    • parse_query
    • pre_get_posts
    • wp
  • Templat dipilih:
    • template_redirect
  • Template dimuat / keluaran. Tindakan berikut dipecat oleh templat :
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Jadi,, the_postdipecat oleh the_post(), terjadi lama setelah kueri diuraikan, posting diambil, dan templat dimuat.

Saya sangat berterima kasih karena Anda memberikan banyak informasi yang saya tidak tahu, tapi ini bukan yang saya minta.

Oh, tapi saya yakin itu persis seperti yang Anda minta.

Pertanyaan sebenarnya adalah: apa itu pengembalian permintaan yang valid ? Untuk konteks seperti indeks arsip kategori, kueri itu valid, dan templat kategori dimuat, jika ID kategori yang ditanyakan ada, bahkan jika tidak ada tulisan yang ditugaskan untuk kategori itu .

Mengapa? Karena kueri yang diuraikan adalah (IIRC) &cat={ID}- yang merupakan permintaan yang valid bahkan jika tidak ada posting yang ditugaskan untuk kategori itu , dan dengan demikian tidak menghasilkan 404 pada penguraian.

Dalam hal itu, Anda mendapatkan kueri yang valid, dan file template dimuat, tetapi tidak ada posting . Dengan demikian, if ( have_posts() ), , pada kenyataannya relevan. Sekali lagi, ini adalah contohnya: kategori ada, tetapi tidak memiliki posting yang ditetapkan. File templat kategori dimuat, dengan if ( have_posts() )pengembalianfalse .

Ini tidak akan berlaku untuk kueri yang menyertakan variabel posting ( &p={ID}) seperti posting blog tunggal dan halaman statis, karena posting tersebut tidak benar-benar ada, dan ketika diuraikan, kueri tidak akan mengembalikan objek yang valid.

Edit 2

Jika saya benar memahami jika tidak ada if (have_posts ()) dalam templat kategori dan kategorinya tidak memiliki kiriman, maka ia mengembalikan 404.php, meskipun itu seharusnya mengembalikan kategori-sample.php tanpa kiriman. Apakah itu benar?

Ingat: templat dipilih di template_redirect. Jadi jika kueri jika valid, maka file templat yang sesuai dimuat. Jika kueri tidak valid, maka templat 404 dimuat.

Jadi, begitu template dimuat - misalnya templat kategori - setelah loop di-output, template tidak berubah .

Lihat kembali urutan tindakan:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- Templat dipilih dan dimuat di sini. Ini adalah titik templat tidak dapat kembali . Templat tidak dapat berubah setelah titik ini.
  • ...
  • the_post- postdata diatur di sini, sebagai bagian dari panggilan putaran. Ini disebut di dalam templat , dan templat tidak berubah berdasarkan data yang tersedia di objek kueri

Edit Terakhir

Dan saya mengklaim bahwa ketika memeriksa keberadaan posting, mengapa saya harus menjalankan tes yang sama dua kali. Itulah pertanyaan saya dari poin pertama yang saya tanyakan hanya tentang itu.

Dan dengan itu, saya akhirnya mengerti: selama ini, pertanyaan Anda tidak ada hubungannya dengan WordPress , atau WordPress Loop . Anda bertanya tentang membungkus whileloop PHP sewenang-wenang di dalam ifkondisi yang memeriksa kondisi yang sama.

Pertanyaan itu di luar lingkup WPSE, tapi saya akan jelaskan secara singkat:

Suatu ifkondisi adalah evaluasi biner: itu adalah salah satu trueatau false, dan apa yang terjadi di dalam kondisi itu dieksekusi sekali .

Sebuah whilekondisional adalah sebuah loop : ia tetap benar untuk beberapa periode diskrit, berdasarkan pada semacam counter; dan apa yang terjadi di dalam kondisi itu dieksekusi beberapa kali - satu kali untuk setiap iterasi dari counter.

Jadi, katakanlah Anda ingin menampilkan daftar hal-hal yang tidak terurut, jika daftar hal-hal tersebut terisi. Jika Anda menggunakan whileloop, dan menghilangkan ifpembungkus, markup Anda akan terlihat seperti ini:

<ul>
<?php while ( list_of_things() ) : ?>
    <li><?php the_list_item(); ?></li>
<?php endwhile; ?>
</ul>

Dan jika list_of_things()kosong, output yang diberikan adalah:

<ul>
</ul>

Yang meninggalkan markup yang tidak perlu (dan tidak valid).

Tetapi jika Anda menambahkan ifpembungkus bersyarat, Anda bisa melakukan ini:

<?php if ( list_of_things() ) : ?>
    <ul>
    <?php while ( list_of_things() ) : ?>
        <li><?php the_list_item(); ?></li>
    <?php endwhile; ?>
    </ul>
<?php endif; ?>

Dan jika list_of_things()kosong, tidak ada markup sama sekali akan menjadi output.

Itu hanya satu contoh. Ada banyak kegunaan untuk ifpembungkus bersyarat itu, dan ifpembungkus bersyarat melayani tujuan yang sama sekali berbeda dari whileloop.

Chip Bennett
sumber
2
Dalam templat posting / halaman tunggal saya, sejak lama, saya hanya menggunakan the_post();karena juga whiletidak perlu. +1 untuk kelengkapan informasi.
gmazzap
@ GM Mungkin menghapus if( have_posts() )pernyataan itu masuk akal (itulah yang saya coba cari tahu), tetapi jangan hanya gunakan the_post()di halaman tunggal!
Sunyatasattva
@ChipBennett Semua dipertimbangkan, apakah Anda pikir aman untuk menghapus if( have_post() )kondisi sebelum loop penuh dalam konteks single-*.phpdan page-*.phptemplat file?
Sunyatasattva
1
"Aman" benar-benar tidak memiliki arti yang pasti dalam konteks ini.
Chip Bennett
10

Sangat tidak mungkin untuk memperbaiki jawaban Chip, tetapi hanya untuk memotong untuk mengejar:

Gunakan ifbagian ini jika Anda ingin menampilkan sesuatu yang berbeda saat tidak ada pos . Ini sangat berguna, misalnya, pada halaman arsip tanggal atau kategori. Jika seseorang menavigasi ke halaman yang tidak memiliki posting, senang memiliki pesan yang mengatakannya, daripada hanya tidak muncul sama sekali, karena loop tidak pernah dieksekusi.

if ( have_posts() ):
  // Yep, we have posts, so let's loop through them.
  while ( have_posts() ) : the_post();
  // do your loop
  endwhile;
else :
  // No, we don't have any posts, so maybe we display a nice message
  echo "<p class='no-posts'>" . __( "Sorry, there are no posts at this time." ) . "</p>";
endif;
Tom Auger
sumber
Dan ini semua yang perlu diketahui.
Herbert Van-Vliet
0

Mungkin ada beberapa pertimbangan yang tidak dimasukkan dalam jawaban sejauh ini. Tidak disarankan untuk menghilangkan pernyataan if.

Pernyataan if biasanya digunakan untuk:

  • Keluarkan sesuatu yang ingin no posts foundmenunjukkan bahwa kategori tersebut tidak memiliki artikel yang ditugaskan untuk itu.
  • untuk memutuskan apakah sekitar html (seperti ul) harus di-output sebelum dan sesudah artikel.

Bagaimana jika sebuah kait baru ditambahkan?

Kemungkinan masalah lain dari tidak menggunakan pernyataan if adalah bahwa jika tim wordpress pernah memutuskan untuk menambahkan hook baru yang memicu pada $wp_query->have_posts()panggilan pertama , itu akan memicu pada waktu yang salah. Dan jika itu menyebabkan perilaku tak terduga, itu akan menjadi kesalahan Anda karena tidak mengikuti spesifikasi dengan benar.

Pengembang lainnya berharap untuk melihat struktur spesifik untuk loop wordpress

Saya kira pengembang lain berharap untuk melihat seluruh loop wordpress. Jadi mungkin itu ide yang buruk untuk meminta mereka mencari pernyataan if yang tidak ada.

RMo
sumber
-1

Saya melihat ini sebagai pertanyaan mendasar dari teori struktur kontrol. Blok terlampir dalam loop sementara tidak mengeksekusi bahkan sekali jika kondisi (have_posts ()) mengevaluasi sebagai false pertama kali.

Jadi, tujuan dari if ( have_posts() )loop WordPress hanya untuk mengeksekusi fungsi have_posts () satu kali sebelum kondisi sementara dievaluasi. Jika have_posts()tidak memiliki efek samping, maka if ( have_posts() )sama sekali tidak ada gunanya. Jika have_posts()memang memiliki efek samping, Anda dapat menyederhanakan sebagai berikut:

<?php have_posts(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
Schparky
sumber
3
Penyederhanaan itu adalah PHP yang tidak valid, Anda memiliki pernyataan lain yang tidak memiliki pernyataan jika terlampir. Paling-paling sulit dibaca
Tom J Nowell
1
Ada di ifsana karena elsesetelahnya. Tidak ada alasan lain. Jika tidak ada posting, maka menampilkan pesan "no posts" yang bagus lebih baik daripada tidak menampilkan apa pun.
Otto