ทำไมฉันถึงต้องใส่ถ้า (have_posts ()) อยู่ในขณะที่ (have_posts ()) ไม่พอ?


22

ฉันมีคำถามเกี่ยวกับ "วง"

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

รหัสนำมาจากหน้าห่วง WordPress Codex

ทำไมฉันถึงต้องมีifส่วนร่วม? ดูเหมือนว่าหากมีการwhileวนซ้ำก็ใช้งานได้ดี

ในกรณีใดปัญหาเกิดขึ้นหากไม่มีifคำสั่ง?

แก้ไข

ฉันยอมรับคำตอบของ @ Chip แต่พูดอย่างสุจริตว่าฉันต้องการเพียงส่วนสุดท้าย

ตอนนี้ฉันรู้สิ่งที่ฉันอยากรู้จากคำถามของฉัน

ifคำสั่งเป็นเพียงเมื่อจำเป็นถ้าคุณต้องการที่จะนำส่วนหัวหรือส่วนท้ายที่ควรจะเขียนเพียงครั้งเดียว หากคุณไม่ได้ใช้ "wrapper" ifคำสั่งนั้นไม่จำเป็น


2
ฉันโหวตก่อนที่จะอ่าน the_content the_title นั้นเด็ดขาด!
brasofilo

ยอดเยี่ยม (สุดท้าย) แก้ไข คนส่วนใหญ่ใช้ถ้าและในขณะที่โดยตรงหลังจากกันและกันโดยไม่เคยใช้อย่างอื่น อาจเป็นเพราะคัดลอกและวาง
Herbert Van-Vliet

คำตอบ:


29

เทมเพลตโหลดเดอร์เทมเพลต WordPress จะรวมไฟล์เทมเพลตบริบทที่เหมาะสมในหลาย ๆ สถานการณ์แม้ว่าการสืบค้นสำหรับบริบทนั้นจะไม่มีการโพสต์ ตัวอย่างเช่น:

  • ดัชนีโพสต์บล็อกหลัก
  • ดัชนีที่เก็บหมวดหมู่ (มีอยู่ แต่ไม่มีโพสต์)
  • ดัชนีคลังแท็ก (มีแท็กแล้ว แต่ไม่มีโพสต์)
  • ดัชนีผู้แต่งถาวร (มีอยู่ แต่ไม่มีโพสต์)
  • ดัชนีผลการค้นหา

ดังนั้นในกรณีนี้ไฟล์เทมเพลตที่เหมาะสมจะถูกโหลด แต่จะไม่มีการโพสต์ข้อความใด ๆ

ตัวอย่างการพิสูจน์แนวคิด:

ดังนั้นในบริบทเหล่านี้จะเป็นประโยชน์สำหรับไฟล์เทมเพลตที่จะรวม if ( have_posts() )เงื่อนไข

ในบริบทอื่นไฟล์เทมเพลตจะไม่สามารถโหลดได้ถ้าแบบสอบถามไม่ส่งคืนโพสต์ ตัวอย่างเช่น:

  • โพสต์บล็อกเดียว
  • หน้าคงที่

ในบริบทเหล่านี้ if ( have_posts() )อาจไม่จำเป็น

แก้ไข

ฉันเข้าใจว่าการสืบค้นนั้นเรียกใช้โดย the_post () ใช่ไหม และถ้าในขณะที่ (have_posts ()) อยู่แบบสอบถามจะไม่เกิดขึ้นหากไม่มีโพสต์

จะเข้าใจในสิ่งที่เกิดขึ้นคุณจะต้องดูที่คำสั่งของการกระทำเวิร์ดเพรส เริ่มต้นด้วยwp_loaded(และละเว้นบางส่วนเพื่อความชัดเจน):

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

ดังนั้นเกิดอะไรขึ้นและในลำดับใด

  • แบบสอบถามถูกเรียก:
    • parse_query
    • pre_get_posts
    • wp
  • แม่แบบถูกเลือก:
    • template_redirect
  • เทมเพลตถูกโหลด / ส่งออก เทมเพลตการดำเนินการต่อไปนี้ถูกเรียกใช้โดย :
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

ดังนั้นthe_postถูกไล่ออกโดยthe_post()เกิดขึ้นนานหลังจากที่แยกวิเคราะห์แบบสอบถามโพสต์จะถูกดึงและแม่แบบถูกโหลด

ฉันขอบคุณมากที่คุณให้ข้อมูลมากมายที่ฉันไม่รู้ แต่นี่ไม่ใช่สิ่งที่ฉันถาม

แต่ฉันเชื่อว่ามันเป็นสิ่งที่แน่นอนสิ่งที่คุณถาม

คำถามจริงคืออะไรแบบสอบถามที่ถูกต้องส่งกลับ ? สำหรับบริบทเช่นดัชนีหมวดหมู่การสืบค้นจะใช้งานได้และมีการโหลดแม่แบบหมวดหมู่หากรหัสหมวดหมู่ที่สอบถามมีอยู่แม้ว่าจะไม่มีการกำหนดโพสต์ในหมวดหมู่นั้นก็ตาม

ทำไม? เนื่องจากเคียวรีที่ถูกวิเคราะห์คำคือ (IIRC) &cat={ID}- ซึ่งเป็นเคียวรีที่ถูกต้องแม้ว่าจะไม่มีโพสต์ที่กำหนดให้กับหมวดหมู่นั้นและดังนั้นจึงไม่ส่งผลให้ 404 เมื่อแยกวิเคราะห์

ในกรณีที่คุณได้รับการสืบค้นที่ถูกต้องและแม่แบบไฟล์โหลดแต่ไม่มีโพสต์ ดังนั้นif ( have_posts() ), ในความเป็นจริงที่เกี่ยวข้อง อีกครั้งนี่คือตัวอย่าง: หมวดหมู่มีอยู่ แต่ไม่มีการกำหนดโพสต์ ไฟล์ประเภทแม่แบบจะเต็มไปด้วยการif ( have_posts() )falseกลับมา

สิ่งนี้จะไม่ถือเป็นจริงสำหรับข้อความค้นหาที่มีตัวแปรโพสต์ ( &p={ID}) เช่นโพสต์บล็อกเดียวและหน้าคงที่เพราะโพสต์จะไม่มีอยู่จริงและเมื่อแยกวิเคราะห์แล้วแบบสอบถามจะไม่ส่งคืนวัตถุที่ถูกต้อง

แก้ไข 2

ถ้าฉันเข้าใจถูกต้องว่าไม่มี (if_posts ()) ในเทมเพลตหมวดหมู่และหมวดหมู่ไม่มีโพสต์ก็จะส่งคืน 404.php แม้ว่ามันควรจะส่งคืน category-sample.php โดยไม่โพสต์ นั่นถูกต้องใช่ไหม?

เลขที่จำเอาไว้: template_redirectแม่แบบที่มีการเลือก ดังนั้นถ้าแบบสอบถามถ้าถูกต้องแล้วไฟล์แม่แบบที่เหมาะสมจะถูกโหลด ถ้าแบบสอบถามไม่ถูกต้องจะมีการโหลดแม่แบบ 404

ดังนั้นเมื่อแม่แบบที่มีการโหลด - เช่นหมวดหมู่แม่แบบ - เมื่อห่วงคือการส่งออกแม่แบบไม่เปลี่ยนแปลง

ดูคำสั่งของการกระทำอีกครั้ง:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- เลือกแม่แบบและโหลดที่นี่ นี้เป็นแม่แบบจุดกลับไม่มี เทมเพลตไม่สามารถเปลี่ยนแปลงได้หลังจากจุดนี้
  • ...
  • the_post- postdata ตั้งค่าไว้ที่นี่เป็นส่วนหนึ่งของการโทรแบบวนซ้ำ สิ่งนี้เรียกว่าภายในแม่แบบและแม่แบบนั้นจะไม่เปลี่ยนแปลงตามข้อมูลที่มีอยู่ในวัตถุแบบสอบถาม

การแก้ไขครั้งสุดท้าย

และฉันอ้างว่าขณะที่ตรวจสอบการมีอยู่ของโพสต์ทำไมฉันควรรันการทดสอบเดียวกันสองครั้ง นั่นคือคำถามของฉันตั้งแต่แรกฉันได้ถามเกี่ยวกับเรื่องนั้นเท่านั้น

และด้วยที่ในที่สุดผมก็เข้าใจทั้งหมดพร้อมคำถามของคุณมีอะไรจะทำอย่างไรกับWordPressหรือWordPress ห่วง คุณกำลังถามเกี่ยวกับการตัดการwhileวนลูปPHP ใด ๆภายในifเงื่อนไขที่ตรวจสอบสภาพเดียวกัน

คำถามนั้นอยู่นอกขอบเขตของ WPSE แต่ฉันจะอธิบายสั้น ๆ :

ifเงื่อนไขคือการประเมินผลไบนารี: มันเป็นอย่างใดอย่างหนึ่งtrueหรือfalseและสิ่งที่เกิดขึ้นภายในของเงื่อนไขที่จะถูกดำเนินการครั้งเดียว

whileเงื่อนไขเป็นห่วงมันยังคงเป็นจริงสำหรับระยะเวลาที่ต่อเนื่องบางส่วนขึ้นอยู่กับการจัดเรียงของเคาน์เตอร์บาง และสิ่งที่เกิดขึ้นภายในเงื่อนไขนั้นจะถูกดำเนินการหลายครั้ง - หนึ่งครั้งสำหรับการวนซ้ำแต่ละครั้งของตัวนับ

ดังนั้นสมมติว่าคุณต้องการแสดงรายการสิ่งที่ไม่เรียงลำดับหากรายการสิ่งต่าง ๆ มีประชากรอยู่ หากคุณใช้การwhileวนซ้ำและไม่ใส่ifเสื้อคลุมมาร์คอัปของคุณจะเป็นดังนี้:

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

และถ้าlist_of_things()ว่างเปล่าผลลัพธ์ที่แสดงจะเป็น:

<ul>
</ul>

สิ่งใดปล่อยให้มาร์กอัปที่ไม่จำเป็น (และไม่ถูกต้อง)

แต่ถ้าคุณเพิ่มในifwrapper ที่มีเงื่อนไขคุณสามารถทำได้ดังนี้

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

และถ้าlist_of_things()ว่างเปล่าจะไม่มีเอาต์พุตมาร์กอัปเลย

นั่นเป็นเพียงตัวอย่างเดียว มีการใช้งานมากมายสำหรับifwrapper แบบมีเงื่อนไขนั้นและifwrapper แบบมีเงื่อนไขนั้นมีจุดประสงค์ที่แตกต่างไปจากwhileวงอย่างสิ้นเชิง


2
ในแม่แบบโพสต์ / หน้าเอกพจน์ของฉันมาเป็นเวลานานฉันใช้เพียงthe_post();เพราะยังwhileไม่จำเป็น +1 เพื่อความสมบูรณ์ของข้อมูล
gmazzap

@GM การลบif( have_posts() )ข้อความอาจสมเหตุสมผล (นั่นคือสิ่งที่ฉันพยายามค้นหา) แต่ไม่ได้ใช้เฉพาะthe_post()ในหน้าเอกพจน์!
Sunyatasattva

@ChipBennett พิจารณาแล้วคุณคิดว่าการลบif( have_post() )เงื่อนไขก่อนลูปเต็มในบริบทsingle-*.phpและpage-*.phpไฟล์เทมเพลตนั้นปลอดภัยหรือไม่?
Sunyatasattva

1
"ปลอดภัย" ไม่มีความหมายที่ชัดเจนจริงๆในบริบทนี้
Chip Bennett

10

มันเป็นไปไม่ได้จริงๆที่จะปรับปรุงตามคำตอบของ Chip แต่เพื่อตัดการไล่ล่า:

ใช้ifเป็นส่วนหนึ่งถ้าคุณต้องการที่จะมีบางสิ่งบางอย่างที่แตกต่างกันแสดงขึ้นเมื่อมีการโพสต์ไม่มี สิ่งนี้มีประโยชน์เป็นพิเศษตัวอย่างเช่นในวันที่หรือหน้าจัดเก็บหมวดหมู่ หากมีคนนำทางไปยังเพจที่ไม่มีโพสต์ยินดีที่ได้รับข้อความที่แจ้งเช่นนั้นแทนที่จะเป็นเพียงข้อความที่ไม่ปรากฏเลยเนื่องจากไม่มีการวนซ้ำ

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;

และนี่คือทั้งหมดที่หนึ่งต้องรู้
Herbert Van-Vliet

0

อาจมีข้อควรพิจารณาบางประการที่ไม่รวมอยู่ในคำตอบ ไม่แนะนำให้ละเว้นคำสั่ง if

คำสั่ง if มักใช้เพื่อ:

  • แสดงสิ่งที่ต้องการno posts foundระบุว่าหมวดหมู่ที่เป็นปัญหานั้นไม่มีบทความที่ได้รับมอบหมาย
  • เพื่อตัดสินใจว่าควรล้อมรอบ html (เช่น ul) หรือไม่ก่อนและหลังบทความ

เกิดอะไรขึ้นถ้ามีการเพิ่มตะขอใหม่

ปัญหาที่เป็นไปได้อีกประการหนึ่งของการไม่ใช้คำสั่ง if คือถ้าทีมเวิร์ดเพรสตัดสินใจเพิ่ม hook ใหม่ที่เรียกใช้ในการ$wp_query->have_posts()โทรครั้งแรกมันจะเรียกใช้ในเวลาที่ผิด และหากสิ่งนั้นทำให้เกิดพฤติกรรมที่ไม่คาดคิดมันจะเป็นความผิดของคุณที่ไม่ทำตามข้อมูลจำเพาะอย่างถูกต้อง

ผู้พัฒนารายอื่นคาดว่าจะเห็นโครงสร้างที่เฉพาะเจาะจงสำหรับลูป WordPress

ฉันคิดว่านักพัฒนาคนอื่น ๆ คาดหวังว่าจะเห็นทั้ง wordpress loop ดังนั้นอาจเป็นความคิดที่ดีที่จะให้พวกเขาค้นหาคำสั่ง if ที่ไม่มีอยู่


-1

ฉันเห็นสิ่งนี้เป็นคำถามพื้นฐานของทฤษฎีโครงสร้างการควบคุม บล็อกที่ถูกปิดล้อมในขณะที่ลูปไม่ทำงานแม้แต่ครั้งเดียวหากเงื่อนไข (have_posts ()) ประเมินว่าเป็นเท็จในครั้งแรก

ดังนั้นจุดประสงค์ของif ( have_posts() )การวนลูป WordPress ก็เพื่อใช้งานฟังก์ชั่น have_posts () หนึ่งครั้งก่อนที่จะทำการประเมินเงื่อนไข while หากhave_posts()ไม่มีผลข้างเคียงแสดงว่าif ( have_posts() )ไม่มีประโยชน์เลย หากhave_posts()มีผลข้างเคียงคุณสามารถลดความซับซ้อนดังต่อไปนี้:

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

3
การทำให้เข้าใจง่ายนั้นคือ PHP ที่ไม่ถูกต้องคุณมีคำสั่งอื่นที่ไม่ได้แนบถ้ามีคำสั่ง ที่ดีที่สุดมันยากที่จะอ่าน
Tom J Nowell

1
ifมีเพราะelseหลังจากที่มัน ไม่มีเหตุผลอื่น หากไม่มีโพสต์แสดงข้อความ "ไม่มีโพสต์" ที่ดีจะดีกว่าการแสดงอะไร
อ็อตโต
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.