I have a question about “the 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; ?>
Code taken from The Loop WordPress Codex page.
Why should I put if
part?
It seems like if there is while
loop, works fine.
In what case problem occurs if there is no if
statement?
Edit
I accepted @Chip’s answer. but honestly saying I need only last part.
I know now what I wanted to know from my question.
if
statement is only when necessary, if you want to put a header or footer that should be write only once. if you don’t use the “wrapper”, thenif
statement is not necessary.
The WordPress template loader will include the appropriate contextual template file in many circumstances, even if the query for that context returns no posts. For example:
Thus, in these cases, the appropriate template file will be loaded, but no posts will be output, because the query returns no posts.
Proof-of-concept examples:
So, in these contexts, it is useful for the template file to include the
if ( have_posts() )
conditional.In other contexts, the template file will never be loaded if the query returns no posts. For example:
In these contexts,
if ( have_posts() )
is probably unnecessary.Edit
To understand what’s going on, you have to look at the order of WordPress actions. Starting with
wp_loaded
(and omitting some for clarity):wp_loaded
parse_request
send_headers
parse_query
pre_get_posts
wp
template_redirect
get_header
wp_head
the_post
wp_footer
So, what’s happening, and in what order?
parse_query
pre_get_posts
wp
template_redirect
get_header
wp_head
the_post
dynamic_sidebar
get_footer
wp_footer
So,
the_post
, fired bythe_post()
, happens long after the query is parsed, posts are fetched, and the template is loaded.Oh, but I believe that it is exactly what you asked.
The real question is: what is a valid query return? For contexts such as the category archive index, the query is valid, and the category template is loaded, if the queried category ID exists, even if there are no posts assigned to that category.
Why? Because the query being parsed is (IIRC)
&cat={ID}
– which is a valid query even if there are no posts assigned to that category, and thus doesn’t result in a 404 upon parsing.In that case, you get a valid query, and a template file loaded, but no posts. Thus,
if ( have_posts() )
, is, in fact relevant. Again, here is an example: category exists, but has no posts assigned. Category template file is loaded, withif ( have_posts() )
returningfalse
.This won’t hold true for queries that include a post variable (
&p={ID}
) such as single blog posts and static pages, because the post won’t actually exist, and when parsed, the query will not return a valid object.Edit 2
No. Remember: the template is selected at
template_redirect
. So if the query if valid, then the appropriate template file is loaded. If the query is not valid, then the 404 template is loaded.So, once a template is loaded – e.g. the category template – once the loop is output, the template does not change.
Look again at the order of actions:
parse_query
pre_get_posts
wp
template_redirect
– template is chosen and loaded here. This is the template point of no return. The template cannot change after this point.the_post
– postdata is setup here, as part of the loop call. This is called inside the template, and the template does not change based on available data in the query objectFinal Edit
And with that, I finally understand: all along, your question had nothing to do with WordPress, or the WordPress Loop. You’re asking about wrapping any arbitrary PHP
while
loop inside anif
conditional that checks the same condition.That question is outside the scope of WPSE, but I’ll briefly explain:
An
if
conditional is a binary evaluation: it’s eithertrue
orfalse
, and what happens inside of that conditional is executed once.A
while
conditional is a loop: it remains true for some discrete period, based on some sort of counter; and what happens inside of that conditional is executed several times – once for each iteration of the counter.So, let’s say that you want to output an unordered list of things, if the list of things is populated. If you use a
while
loop, and omit theif
wrapper, your markup would look like this:And if
list_of_things()
was empty, the rendered output would be:Which leaves unnecessary (and invalid) markup.
But if you add in an
if
conditional wrapper, you can do this:And if
list_of_things()
was empty, no markup at all would be output.That’s just one example. There are lots of uses for that
if
conditional wrapper, and theif
conditional wrapper serves an entirely different purpose than thewhile
loop.It’s really impossible to improve on Chip’s answer, but just to cut to the chase:
Use the
if
part if you want to have something different show up when there are no posts. This is particularly useful, for example, on a date or category archive page. If someone navigates to a page that has no posts, it’s nice to have a message that says so, rather than just nothing appearing at all, because the loop never gets executed.There may be some considerations that are not included in the answers so far. It is not recommended to omit the if statement.
The if statement is commonly used to:
no posts found
to indicate that the category in question has no articles assigned to it.What if a new hook is added?
Another possible issue of not using the if statement is that if the wordpress team ever decided to add a new hook that triggers on the first
$wp_query->have_posts()
call, it would trigger at the wrong time. And if that causes unexpected behavior it would be your fault for not following the spec properly.Other devs expect to see a specific structure for the wordpress loop
I suppose other developers expect to see the entire wordpress loop. So maybe it is a bad idea to have them searching for an if statement that isn’t there.
I see this as a fundamental question of control structure theory. The enclosed block within the while loop doesn’t execute even once if condition (have_posts()) evaluates as false the first time.
So, the the purpose of
if ( have_posts() )
in the WordPress loop is only to execute the function have_posts() once before the while condition is evaluated. Ifhave_posts()
has no side-effects, then theif ( have_posts() )
is totally pointless. Ifhave_posts()
does have side-effects, you could simplify as follows: