Creating custom post loops for WordPress

Posted on 7th January, 2016 Leave a Comment

So I know this has a ton of coverage on Google, but I thought I would add my own post on the subject as I use this blog as my own reference (which is the entire reason I created this site) with a few examples.

Let me give you a quick breakdown of how a custom loop works.

  1. You would generally start off with your arguments for the loop.
    A full list of arguments can be seen here https://gist.github.com/luetkemj/2023628
  2. Then create a new WP_Query and assign the arguments to it.
    https://codex.wordpress.org/Class_Reference/WP_Query
  3. Which is then used to check and display your posts.

You can control all kinds of things with a custom post loop, most recently I had to create 3 loops for a single blog page.
The first loop I needed was to only grab the sticky posts which were under a particular category “alerts”.

Example below:

<?php 
$sticky = get_option( 'sticky_posts' ); /* GRAB THE STICKY POST OPTION */
if (is_front_page() && $sticky) {
$args = array(
	  'post__in'			=> $sticky,
	  'posts_per_page'		=> 5, /* SHOW A MAXIMUM 5 POSTS */
	  'category_name'		=> 'alert', /* IF THEY ARE IN THE CATEGORY "ALERT" */
	  'no_found_rows'		=> true,
	  'ignore_sticky_posts' => 1
	);	
	
$sticky_query = new WP_Query($args); /* SET THE NEW QUERY WITH THE ABOVE ARGS */
?>	

<?php if ( $sticky_query->have_posts() ) { /* CHECK THE ARGUMENTS AGAINST THE POSTS */ ?>
			<div id="alert">
				<div class="wrapper">
					<div class="close"><i class="fa fa-times"></i></div>
					<div class="ticker">
						<ul>
			<?php while ( $sticky_query->have_posts() ) : $sticky_query->the_post(); /* FINALLY OUTPUT THE CUSTOM LOOP */ ?>
						<li>
						<strong><?php the_title(); ?> - </strong>
						<?php the_excerpt(); ?>
						</li>
			<?php endwhile; ?>
						</ul>
					</div>
				</div>
			</div>
<?php  wp_reset_postdata(); } } /* MAKE SURE YOU RESET YOUR LOOP! */ ?>	

The second loop I used was to grab only the first most recent post from the blog as I had set a featured/larger post section to display this.

<?php if(have_posts()) :?>
	
	  <?php
          $args = array('posts_per_page' => 1);  /* GRAB ONLY THE FIRST POST */
          $loop = new WP_Query( $args );
          while ( $loop->have_posts() ) : $loop->the_post(); ?>
		
		<div class="first-post clearfix">
			<article>
				<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
				<p><small>Published <?php the_time('M jS, Y'); ?> by <?php the_author(); ?></small></p>
				<p><?php $content = get_the_content(); 
						echo wp_trim_words($content, '30', '... '); ?></p>
                <a href="<?php the_permalink(); ?>" class="readmore">Read More</a>
			</article>
            <a href="<?php the_permalink(); ?>">
			<?php if (has_post_thumbnail()) {
						if ( strlen( $img = get_the_post_thumbnail( get_the_ID(), array( 150, 150 ) ) ) ) {
							echo get_the_post_thumbnail($post->ID, 'blog-feature');
						} else {
							 echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-feature.jpg" />';
						}					  
					} else {
					   echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-feature.jpg" />';
					} ?></a>
		</div><!-- /.first-post -->
	<?php endwhile; wp_reset_postdata(); ?>

The third loop was to just show the rest of the blog posts as normal, but making sure that I didn’t show the first post OR keep the sticky post at the top of the articles.

<div class="posts">
			 <?php
			  $args2 = array(
			  			'offset' => 1, /* REMOVE THE FIRST POST FROM THIS LOOP */
						'ignore_sticky_posts' => 1 /* IGNORE THE STICKY POSTS "STICK-ABILITY" */
						);  
			  $loop2 = new WP_Query( $args2 );
			  while ( $loop2->have_posts() ) : $loop2->the_post(); ?>
				<div class="single clearfix">
					<a href="<?php the_permalink(); ?>">
					 <?php if (has_post_thumbnail()) {
								if ( strlen( $img = get_the_post_thumbnail( get_the_ID(), array( 150, 150 ) ) ) ) {
									echo get_the_post_thumbnail($post->ID, 'blog-icon');
								} else {   
									echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-icon.jpg" />';
								}
							} else {
							   echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-icon.jpg" />';
							} ?></a>
					<article>
						<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
						<p><small>Published <?php the_time('M jS, Y'); ?> by <?php the_author(); ?></small></p>
						<a href="<?php the_permalink(); ?>" class="readmore">Read More</a>
					</article>
				</div>		
						
			<?php endwhile;  wp_reset_postdata(); ?>
</div> <!-- /.posts -->

Lastly, if you’re using pagination on your posts you’ll find that you’ll need a new loop when your paging.
So you will need to create a fourth loop and wrap the above loop in a controlling if statement.

	
		<div class="posts">
		<?php if(!is_paged()) { /* CHECK IF WE'RE ON PAGE 1 OF THE POSTS */ ?> 
			 <?php
			  $args2 = array(
			  			'offset' => 1,
						'ignore_sticky_posts' => 1
						);  
			  $loop2 = new WP_Query( $args2 );
			  while ( $loop2->have_posts() ) : $loop2->the_post(); ?>
				<div class="single clearfix">
					<a href="<?php the_permalink(); ?>">
					 <?php if (has_post_thumbnail()) {
								if ( strlen( $img = get_the_post_thumbnail( get_the_ID(), array( 150, 150 ) ) ) ) {
									echo get_the_post_thumbnail($post->ID, 'blog-icon');
								} else {   
									echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-icon.jpg" />';
								}
							} else {
							   echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-icon.jpg" />';
							} ?></a>
					<article>
						<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
						<p><small>Published <?php the_time('M jS, Y'); ?> by <?php the_author(); ?></small></p>
						<a href="<?php the_permalink(); ?>" class="readmore">Read More</a>
					</article>
				</div>		
						
			<?php endwhile;  wp_reset_postdata(); ?>

		<?php } else { // OTHERWISE WE'LL USE THE STANDARD LOOP... ?>
		
			<?php while ( have_posts() ) : the_post(); ?>
			<div class="single clearfix">
                <a href="<?php the_permalink(); ?>">
				 <?php if (has_post_thumbnail()) {
							if ( strlen( $img = get_the_post_thumbnail( get_the_ID(), array( 150, 150 ) ) ) ) {
								echo get_the_post_thumbnail($post->ID, 'blog-icon');
							} else {   
								echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-icon.jpg" />';
							}
						} else {
						   echo '<img src="' . get_bloginfo('template_directory') . '/images/blog/default-blog-icon.jpg" />';
						} ?></a>
				<article>
					<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
					<p><small>Published <?php the_time('M jS, Y'); ?> by <?php the_author(); ?></small></p>
                    <a href="<?php the_permalink(); ?>" class="readmore">Read More</a>
				</article>
            </div>	
		
		<?php endwhile; } //is_paged() end ?>
		<?php endif; ?>	
			
			<?php post_pagination(); ?>
			
		</div> <!-- /.posts -->

Leave a Comment

To preserve code added to a comment you can wrap your code in short tags
by using [square brackets]:

  1. PHP use - [php] <?php code here ?> [/php]
  2. CSS use - [css] #code-here {} [/css]
  3. HTML use - [html] <div> code here </div> [/html]
  4. JS use - [js] $(".codeHere") [/js]