The Loop
By the time a template loads, WordPress has already parsed the address and fetched the right posts from the database: a single article, a category list or search results. The template only has to print them. A construct simply called "the Loop" does that.
The Loop itself
<?php
// index.php
if (have_posts()) :
while (have_posts()) :
the_post();
?>
<article>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
</article>
<?php
endwhile;
else :
?>
<p>No posts yet.</p>
<?php
endif;have_posts() checks whether posts remain. the_post() makes the next post the current one — after that the output functions know which post to work with.
Output functions
| Function | What it prints |
|---|---|
the_title() | The title |
the_content() | The full text |
the_excerpt() | A short summary |
the_permalink() | The post address |
the_post_thumbnail('medium') | The featured image |
the_author() | The author's name |
the_category(', ') | Categories with links |
the_tags() | Tags |
the_ID() | The identifier |
These functions work only inside the Loop.
the_ and get_the_
Functions with the the_ prefix print the value at once. Their get_the_ counterparts return it — for checks and your own transformations:
<?php
// content.php
$title = get_the_title();
?>
<h2 class="<?php echo strlen($title) > 60 ? 'title-long' : 'title'; ?>">
<?php echo esc_html($title); ?>
</h2>
<time datetime="<?php echo esc_attr(get_the_date('c')); ?>">
<?php echo esc_html(get_the_date('F j, Y')); ?>
</time>Values obtained through get_ are escaped with esc_html() and esc_attr() before output.
The featured image
<?php
// content.php
if (has_post_thumbnail()) {
the_post_thumbnail('large', ['class' => 'cover', 'loading' => 'lazy']);
}WordPress creates the thumbnail, medium, large and full sizes when an image is uploaded. add_image_size('card', 600, 400, true) in functions.php adds your own size.
A single post
The template of a single article is built the same way — the Loop just has one post:
<?php
// single.php
get_header();
while (have_posts()) :
the_post();
?>
<article>
<h1><?php the_title(); ?></h1>
<div class="content"><?php the_content(); ?></div>
</article>
<?php
endwhile;
get_footer();Pagination
How many posts go on a page is set under "Settings → Reading". One function prints the links to neighbouring pages:
<?php
// index.php
the_posts_pagination([
'prev_text' => '← Back',
'next_text' => 'Next →',
]);Common mistake
Without the the_post() call the Loop becomes infinite: have_posts() always returns true because the current post never changes, and the page hangs. The while (have_posts()) and the_post() lines always go together.