なぜif(have_posts())を入れなければならないのに、while(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; ?>

The Loop WordPress Codexページから取られたコード。

なぜ私はif部分を置くべきですか?whileループがあればうまくいくようです。

ifステートメントがない場合、どのような場合に問題が発生しますか?

編集

@Chipの答えを受け入れました。正直言って、最後の部分だけが必要だと言っています。

私は自分の質問から知りたいことを知っています。

if一度だけ書き込むヘッダーまたはフッターを配置する場合、ステートメントは必要な場合にのみ使用します。「ラッパー」を使用しない場合、ifステートメントは不要です。


2
the_contentを読む前に投票しました。the_titleが決定的です!
ブラソフィロ

優れた(最終)編集。ほとんどの人は、elseを使用せずにifとwhileを直接使用します。おそらくコピー&ペーストが原因です。
ハーバートヴァンフリート

回答:


29

WordPressテンプレートローダーには、多くの状況で、そのコンテキストのクエリが投稿を返さない場合でも、適切なコンテキストテンプレートファイルが含まれます。例えば:

  • メインのブログ投稿インデックス
  • カテゴリアーカイブインデックス(カテゴリは存在しますが、投稿はありません)
  • タグアーカイブインデックス(タグは存在しますが、投稿はありません)
  • 著者アーカイブインデックス(著者は存在しますが、投稿はありません)
  • 検索結果インデックス

したがって、これらの場合、適切なテンプレートファイルが読み込まれますが、クエリは投稿を返さないため、投稿は出力されません。

概念実証の例:

そのため、これらのコンテキストでは、テンプレートファイルにif ( have_posts() )条件を含めると便利です。

他のコンテキストでは、クエリが投稿を返さない場合、テンプレートファイルはロードされません。例えば:

  • 単一のブログ投稿
  • 静的ページ

これらのコンテキストでif ( have_posts() )は、おそらく不要です。

編集

クエリはthe_post()によって呼び出されることを理解していますか?また、while(have_posts())が存在する場合、投稿がないとクエリは発生しません。

何が起こっているのかを理解するには、WordPressアクションの順序を確認する必要があります。開始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()は、クエリが解析され、投稿がフェッチされ、テンプレートがロードされた長時間かかります。

私が知らなかった多くの情報を提供してくれたことに感謝していますが、これは私が尋ねたものではありません。

ああ、でもそれはまさにあなたが尋ねたものだと思う。

本当の問題は、有効なクエリリターンとは何ですか?カテゴリアーカイブインデックスなどのコンテキストでは、クエリが有効で、クエリされたカテゴリIDが存在する場合、そのカテゴリに割り当てられた投稿がない場合でもカテゴリテンプレートがロードされます

どうして?解析されるクエリは(IIRC)&cat={ID}であるためです。これは、そのカテゴリ割り当てられた投稿がない場合でも有効なクエリであり、解析時に404になりません。

その場合、有効なクエリとテンプレートファイルが読み込まれますが、投稿はありません。このように、if ( have_posts() )実際には、ある関連します。繰り返しますが、ここに例があります:カテゴリは存在しますが、投稿は割り当てられていません。カテゴリテンプレートファイルが読み込まれ、がif ( have_posts() )返されfalseます。

これは、単一のブログ投稿や静的ページなどの投稿変数(&p={ID})を含むクエリには当てはまりません。これは、投稿が実際には存在せず、解析時にクエリが有効なオブジェクトを返さないためです。

編集2

カテゴリテンプレートにif(have_posts())がなく、カテゴリに投稿がない場合、私が正しく理解している場合、投稿なしでcategory-sample.phpを返す必要がありますが、404.phpを返します。そうですか?

いいえ。覚えておいてください。テンプレートはで選択されていtemplate_redirectます。クエリが有効であれば、適切なテンプレートファイルがロードされます。クエリが無効な場合、404テンプレートがロードされます。

そのため、テンプレート(カテゴリテンプレートなど)が読み込まれると、ループが出力されると、テンプレートは変更されません

アクションの順序をもう一度見てください。

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- テンプレートが選択され、ここにロードされます。これは、戻り値のないテンプレートポイントです。この時点以降、テンプレートは変更できません。
  • ...
  • the_post- ループ呼び出しの一部として、postdataがここでセットアップされます。これが呼び出され、テンプレート内、およびテンプレートは変更されませんクエリオブジェクトで利用可能なデータに基づいて、

最終編集

そして、投稿の存在を確認しながら、同じテストを2回実行する必要があると主張しています。それは最初の点から私がそれについてだけ尋ねてきた私の質問です。

ことで、私は最終的に理解:すべてに沿って、あなたの質問は、とは何の関係もなかったワードプレス、またはWordPressのループを。同じ条件をチェックwhileするif条件内に任意のPHP ループをラップすることを求めています。

この質問はWPSEの範囲外ですが、簡単に説明します。

if条件は、バイナリの評価である:それはどちらかだtruefalse、そして何が起こるの内部、条件のが実行された後

while条件付きではあるループ:それはカウンターのいくつかの並べ替えに基づいて、いくつかの離散的な期間のための真のまま。そして、その条件の内部で何が起こるは、数回実行されます - カウンターの各反復に対して1回です。

そのため、物のリストにデータが入力されている場合、物の順序付けられていないリストを出力するとします。whileループを使用し、ifラッパーを省略すると、マークアップは次のようになります。

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

そして、もしlist_of_things()空だった、レンダリングされた出力は次のようになります。

<ul>
</ul>

不要な(そして無効な)マークアップが残ります。

ただし、if条件付きラッパーを追加すると、次のことができます。

<?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()空だった、全くのマークアップは出力されないだろう。

それはほんの一例です。そのif条件付きラッパーには多くの用途があり、if条件付きラッパーはループまったく異なる目的を果たしwhileます。


2
私の特異な投稿/ページテンプレートでは、長い間、私も使用the_post();するのwhileは不要だからです。情報の完全性のために+1。
gmazzap

@GMおそらくif( have_posts() )ステートメントを削除することは理にかなっています(私が見つけようとしていることです)が、単数のページだけで使用しないでくださいthe_post()
-Sunyatasattva

@ChipBennettすべては、あなたがそれを削除しても安全だと思いますか、と考えif( have_post() )フルの文脈でループ前の状態にsingle-*.phpし、page-*.phpテンプレートファイル?
-Sunyatasattva

1
この文脈では、「安全」には決定的な意味はありません。
チップベネット

10

チップの答えを改善することは本当に不可能ですが、追いかけるだけです。

投稿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;

そして、これは知っておく必要があるすべてです。
ハーバートヴァンフリート

0

これまでの回答には含まれていない考慮事項があるかもしれません。ifステートメントを省略することはお勧めしません。

ifステートメントは一般的に次の目的で使用されます。

  • no posts found問題のカテゴリに記事が割り当てられていないことを示すようなものを出力します。
  • 記事の前後に(ulのような)周囲のhtmlを出力するかどうかを決定します。

新しいフックが追加されたらどうなりますか?

ifステートメントを使用しない別の考えられる問題は、ワードプレスチームが最初の$wp_query->have_posts()呼び出しでトリガーする新しいフックを追加することに決めた場合、間違ったタイミングでトリガーすることです。そして、それが予期しない動作を引き起こす場合、仕様に正しく従わないことはあなたのせいです。

他の開発者は、ワードプレスループの特定の構造を見ることを期待しています

他の開発者はワードプレスのループ全体を見ることを期待していると思います。したがって、そこにないifステートメントを検索させるのは悪い考えかもしれません。


-1

これは、制御構造理論の基本的な問題だと思います。whileループ内の囲まれたブロックは、条件(have_posts())が最初にfalseと評価された場合でも1回も実行されません。

そのためif ( have_posts() )、WordPressループの目的は、while条件が評価される前に関数have_posts()を1回だけ実行することです。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です。ifステートメントが付加されていないelseステートメントがあります。せいぜい読みにくい
トムJノウェル

1
それifelseその後のためです。他の理由はありません。投稿がない場合は、何も表示しないよりも、「投稿なし」という素敵なメッセージを表示することをお勧めします。
オットー14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.