Tại sao tôi nên đặt if (have_posts ()), trong khi (have_posts ()) không đủ?


22

Tôi có một câu hỏi về "vòng lặp".

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

Mã được lấy từ trang The Loop WordPress Codex .

Tại sao tôi nên đặt ifmột phần? Có vẻ như nếu có whilevòng lặp, hoạt động tốt.

Trong trường hợp vấn đề xảy ra nếu không có iftuyên bố?

Chỉnh sửa

Tôi chấp nhận câu trả lời của @ Chip. nhưng thành thật mà nói tôi chỉ cần phần cuối cùng.

Tôi biết bây giờ những gì tôi muốn biết từ câu hỏi của tôi.

ifcâu lệnh chỉ khi cần thiết, nếu bạn muốn đặt một tiêu đề hoặc chân trang chỉ nên viết một lần. nếu bạn không sử dụng "trình bao bọc", thì ifcâu lệnh là không cần thiết.


2
Tôi đã bỏ phiếu trước khi đọc the_content, the_title mang tính quyết định!
brasofilo

Tuyệt vời (cuối cùng) chỉnh sửa. Hầu hết mọi người sử dụng if và while trực tiếp với nhau mà không bao giờ sử dụng một cái khác. Có khả năng vì sao chép và dán.
Herbert Van-Vliet

Câu trả lời:


29

Trình tải mẫu WordPress sẽ bao gồm tệp mẫu theo ngữ cảnh phù hợp trong nhiều trường hợp, ngay cả khi truy vấn cho ngữ cảnh đó không trả về bài đăng nào. Ví dụ:

  • Chỉ mục bài viết trên Blog chính
  • Danh mục Lưu trữ Danh mục (Danh mục tồn tại, nhưng không có bài đăng)
  • Thẻ lưu trữ chỉ mục (Thẻ tồn tại, nhưng không có bài viết)
  • Chỉ mục Lưu trữ Tác giả (Tác giả tồn tại, nhưng không có bài đăng)
  • Chỉ số kết quả tìm kiếm

Do đó, trong những trường hợp này, tệp mẫu thích hợp sẽ được tải, nhưng không có bài đăng nào được xuất ra, vì truy vấn không trả về bài viết nào.

Ví dụ bằng chứng về khái niệm:

Vì vậy, trong các bối cảnh này, rất hữu ích cho tệp mẫu để bao gồm các if ( have_posts() )điều kiện.

Trong các bối cảnh khác, tệp mẫu sẽ không bao giờ được tải nếu truy vấn không trả về bài viết. Ví dụ:

  • Bài đăng trên blog
  • Trang tĩnh

Trong những bối cảnh này, if ( have_posts() )có lẽ là không cần thiết.

Chỉnh sửa

Tôi hiểu truy vấn được gọi bởi the_post (), phải không? Và nếu while (have_posts ()) tồn tại, truy vấn sẽ không bao giờ xảy ra nếu không có bài đăng.

Để hiểu những gì đang xảy ra, bạn phải xem thứ tự các hành động của WordPress . Bắt đầu với wp_loaded(và bỏ qua một số cho rõ ràng):

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

Vì vậy, những gì đang xảy ra, và theo thứ tự?

  • Truy vấn được gọi:
    • parse_query
    • pre_get_posts
    • wp
  • Mẫu được chọn:
    • template_redirect
  • Mẫu được tải / đầu ra. Các hành động sau đây được kích hoạt bởi mẫu :
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Vì vậy, được the_postkích hoạt bởi the_post(), xảy ra rất lâu sau khi truy vấn được phân tích cú pháp, các bài đăng được tìm nạp và mẫu được tải.

Tôi rất biết ơn vì bạn đã cung cấp rất nhiều thông tin mà tôi không biết, nhưng đây không phải là điều tôi đã hỏi.

Ồ, nhưng tôi tin rằng đó là chính xác những gì bạn yêu cầu.

Câu hỏi thực sự là: trả về truy vấn hợp lệ là gì? Đối với các bối cảnh như chỉ mục lưu trữ danh mục, truy vấn hợp lệ và mẫu danh mục được tải, nếu ID danh mục được truy vấn tồn tại, ngay cả khi không có bài đăng nào được gán cho danh mục đó .

Tại sao? Bởi vì truy vấn đang được phân tích cú pháp là (IIRC) &cat={ID}- đây là một truy vấn hợp lệ ngay cả khi không có bài đăng nào được gán cho danh mục đó và do đó không dẫn đến 404 khi phân tích cú pháp.

Trong trường hợp đó, bạn nhận được một truy vấn hợp lệ và một tệp mẫu được tải, nhưng không có bài đăng . Do đó, if ( have_posts() ), là, trên thực tế có liên quan. Một lần nữa, đây là một ví dụ: thể loại tồn tại, nhưng không có bài viết nào được chỉ định. Tập tin mẫu danh mục được tải, với if ( have_posts() )trả lạifalse .

Điều này sẽ không đúng với các truy vấn bao gồm một biến bài ( &p={ID}) như các bài đăng trên blog và các trang tĩnh, bởi vì bài đăng sẽ không thực sự tồn tại và khi được phân tích cú pháp, truy vấn sẽ không trả về một đối tượng hợp lệ.

Chỉnh sửa 2

Nếu tôi hiểu đúng nếu không có if (have_posts ()) trong mẫu danh mục và danh mục không có bài đăng, thì nó trả về 404.php, mặc dù nó phải trả về category-sample.php mà không cần đăng. Có đúng không?

Không. Hãy nhớ rằng: mẫu được chọn tại template_redirect. Vì vậy, nếu truy vấn nếu hợp lệ, thì tệp mẫu thích hợp được tải. Nếu truy vấn không hợp lệ, thì mẫu 404 được tải.

Vì vậy, một khi mẫu được tải - ví dụ mẫu danh mục - một khi vòng lặp được xuất ra, mẫu không thay đổi .

Nhìn lại thứ tự các hành động:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- mẫu được chọn và tải ở đây. Đây là điểm mẫu không có lợi nhuận . Mẫu không thể thay đổi sau thời điểm này.
  • ...
  • the_post- postdata được thiết lập ở đây, như là một phần của cuộc gọi vòng lặp. Điều này được gọi bên trong mẫumẫu không thay đổi dựa trên dữ liệu có sẵn trong đối tượng truy vấn

Chỉnh sửa cuối cùng

Và tôi khẳng định rằng trong khi kiểm tra sự tồn tại của bài viết, tại sao tôi phải chạy thử nghiệm tương tự hai lần. Đó là câu hỏi của tôi từ điểm đầu tiên tôi chỉ hỏi về điều đó.

Và với điều đó, cuối cùng tôi cũng hiểu: tất cả cùng, câu hỏi của bạn không liên quan gì đến WordPress hay Vòng lặp WordPress . Bạn đang hỏi về việc gói bất kỳ whilevòng lặp PHP tùy ý nào trong một ifđiều kiện kiểm tra cùng một điều kiện.

Câu hỏi đó nằm ngoài phạm vi của WPSE, nhưng tôi sẽ giải thích ngắn gọn:

Một ifđiều kiện là một đánh giá nhị phân: nó hoặc truehoặc false, và những gì xảy ra bên trong điều kiện đó được thực hiện một lần .

Một whileđiều kiện là một vòng lặp : nó vẫn đúng trong một khoảng thời gian riêng biệt, dựa trên một số loại bộ đếm; và những gì xảy ra bên trong điều kiện đó được thực thi nhiều lần - một lần cho mỗi lần lặp của bộ đếm.

Vì vậy, giả sử rằng bạn muốn đưa ra một danh sách các thứ không có thứ tự, nếu danh sách các thứ được điền. Nếu bạn sử dụng mộtwhile vòng lặp và bỏ qua iftrình bao bọc, đánh dấu của bạn sẽ như thế này:

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

Và nếu list_of_things() trống, đầu ra được kết xuất sẽ là:

<ul>
</ul>

Mà để lại đánh dấu không cần thiết (và không hợp lệ).

Nhưng nếu bạn thêm vào if trình bao bọc có điều kiện, bạn có thể làm điều này:

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

Và nếu list_of_things()trống, không có đánh dấu nào được xuất ra.

Đó chỉ là một ví dụ. Có rất nhiều cách sử dụng cho iftrình bao bọc có điều kiện đó và iftrình bao bọc có điều kiện phục vụ một mục đích hoàn toàn khác so với whilevòng lặp.


2
Trong các mẫu bài đăng / trang đơn lẻ của tôi, từ rất lâu, tôi chỉ sử dụng the_post();vì cũng whilekhông cần thiết. +1 cho tính đầy đủ của thông tin.
gmazzap

@GM Có thể loại bỏ if( have_posts() )tuyên bố có ý nghĩa (đó là những gì tôi đang cố gắng tìm hiểu), nhưng không chỉ sử dụng the_post()trong các trang số ít!
Sunyatasattva

@ChipBennett Tất cả được xem xét, bạn có nghĩ rằng an toàn để loại bỏ if( have_post() )điều kiện trước vòng lặp đầy đủ trong ngữ cảnh single-*.phppage-*.phpcác tệp mẫu?
Sunyatasattva

1
"An toàn" thực sự không có ý nghĩa dứt khoát trong bối cảnh này.
Chip Bennett

10

Thật sự không thể cải thiện câu trả lời của Chip, nhưng chỉ để cắt theo đuổi:

Sử dụng ifmột phần nếu bạn muốn có một cái gì đó khác biệt hiển thị khi không có bài viết . Điều này đặc biệt hữu ích, ví dụ, trên trang lưu trữ ngày hoặc danh mục. Nếu ai đó điều hướng đến một trang không có bài đăng, thật tuyệt khi có một thông báo nói như vậy, thay vì không có gì xuất hiện cả, bởi vì vòng lặp không bao giờ được thực thi.

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;

Và đây là tất cả những gì một người cần biết.
Herbert Van-Vliet

0

Có thể có một số cân nhắc không được bao gồm trong các câu trả lời cho đến nay. Không nên bỏ qua câu lệnh if.

Câu lệnh if thường được sử dụng để:

  • xuất ra một cái gì đó như no posts foundđể chỉ ra rằng thể loại trong câu hỏi không có bài viết nào được gán cho nó.
  • để quyết định xem html xung quanh (như ul) có nên xuất ra trước và sau các bài viết không.

Điều gì nếu một hook mới được thêm vào?

Một vấn đề có thể khác của việc không sử dụng câu lệnh if là nếu nhóm wordpress từng quyết định thêm một hook mới kích hoạt vào đầu tiên $wp_query->have_posts() cuộc gọi , nó sẽ kích hoạt không đúng lúc. Và nếu điều đó gây ra hành vi bất ngờ thì đó là lỗi của bạn vì đã không tuân thủ đúng thông số kỹ thuật.

Các nhà phát triển khác hy vọng sẽ thấy một cấu trúc cụ thể cho vòng lặp wordpress

Tôi cho rằng các nhà phát triển khác mong đợi để xem toàn bộ vòng lặp wordpress. Vì vậy, có thể đó là một ý tưởng tồi khi để họ tìm kiếm một câu lệnh if không có ở đó.


-1

Tôi thấy đây là một câu hỏi cơ bản của lý thuyết cấu trúc điều khiển. Khối kèm theo trong vòng lặp while không thực thi ngay cả khi điều kiện (have_posts ()) đánh giá là sai lần đầu tiên.

Vì vậy, mục đích của if ( have_posts() )vòng lặp WordPress chỉ là thực thi hàm have_posts () một lần trước khi điều kiện while được ước tính. Nếu have_posts()không có tác dụng phụ, thì điều đó if ( have_posts() )là hoàn toàn vô nghĩa. Nếu have_posts()không có tác dụng phụ, bạn có thể đơn giản hóa như sau:

<?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
Đơn giản hóa đó là PHP không hợp lệ, bạn có một câu lệnh khác không có câu lệnh if đính kèm. Tốt nhất là rất khó đọc
Tom J Nowell

1
ifđó là vì elsesau nó. Không có lý do khác. Nếu không có bài viết, thì hiển thị một thông báo "không có bài viết" tốt hơn là không hiển thị gì cả.
Otto
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.