Three Ways to Build a WordPress Loop

Posted OnJul 28, 2015     CategoryDevelopment     CommentsNo comment

The WordPress loop is the main element of a WordPress theme. It’s essentially using the WordPress API to fetch posts and post related data, and then displaying them on the front end. If you look at any simple WordPress theme it will probably have a default loop in its index.php.

Though the default loop might be very useful 90% of the time, you might want certain functionality on your WordPress website where the default loop might not cut it. For such scenarios the WordPress system gives you multiple ways to build the a loop. In this article we are going to see what are the different ways we can fetch information from the WordPress system using various WordPress loops to suit our needs.

Using query_posts

As stated above, the default WordPress loop might suffice your needs most of the time. But in some cases you might want slight different behaivor. This can be done by using the query_posts function of WordPress, and changing the parameters per your need. To give you an example, suppose you want the posts to show up in the ascending order of date rather than the default descending order, you can change your main loop (mostly in index.php of your theme) as shown below:

<?php get_header(); 
global $query_string;
query_posts($query_string.'order=ASC');
?>

<div id="primary" class="site-content">
	<div id="content" role="main">

		<?php if ( have_posts() ) : ?>

		<?php /* Start the Loop */ ?>
		<?php while ( have_posts() ) : the_post(); ?>
		<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
			
			<header class="entry-header">
				<?php if ( ! post_password_required() && ! is_attachment() ) :
				the_post_thumbnail();
		    	endif; ?>

				
				<h1 class="entry-title">
					<a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?>
<?php the_date('Y-m-d', '<div class="published-date">Published at ', '</div>'); ?>
					</a>
				</h1>
	
				<?php if ( comments_open() ) : ?>
				<div class="comments-link">
					<?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'twentytwelve' ) . '</span>', __( '1 Reply', 'twentytwelve' ), __( '% Replies', 'twentytwelve' ) ); ?>
				</div>
				<!-- .comments-link -->
				<?php endif; // comments_open() ?>
			</header>
			<!-- .entry-header -->

		
			<div class="entry-content">
				<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentytwelve' ) ); ?>
			</div>

		</article>
		<!-- #post -->
		<?php endwhile; ?>


		<?php endif; // end have_posts() check ?>

	</div>
	<!-- #content -->
</div>
<!-- #primary -->
<?php wp_reset_query();?>
<?php get_sidebar(); ?>
<?php get_footer(); ?>

In the above code we get the default query, which is stored in the global variable $query_string, and the pass the same query string to the function query_posts to add an additional condition as 'order=ASC’. This will display the post in ascending order as shown below.

image001

Using query_posts you can easily change the default loop to display the posts based on your needs. You can add extra conditions to the default query like the one we did above, or completely change the query without using anything from the default query. query_posts has a lot of parameters which can be used to control things like the number of posts, posts from which category appear, and so on. You can see the complete list of parameters for query_post at http://codex.wordpress.org/Function_Reference/WP_Query#Parameters

Though query_post is an easy way to change the main loop, it might be inefficient and increase the page load times as it may cause the work performed to run the query more than two times. Hence, it might be better to hook into the pre_get_posts and alter the query parameter when it’s the main query.

So another way to achieve the posts in ascending order would be to add the following code in functions.php.

function posts_in_ascending_order( $query ) {
    if ( $query->is_main_query() ) {
        $query->set( 'order','ASC' );
    }
}
add_action( 'pre_get_posts', 'posts_in_ascending_order' );

Using WP_Query

In some cases you don’t want to just change the main query, but in fact want multiple loops on the same page to display various data. To do this, WordPress provides the WP_Query class in wp-includes/query.php which can be used to create WordPress loops, and even multiple WordPress loops on the same page. After WP_Query is run you should call wp_reset_postdata() to reset the post data.

So, in case you have a requirement that you want to display all the posts from one category, say ‘front’, prior to any other post, you can create two loops as shown below

<div id="primary" class="site-content">
	<div id="content" role="main">

	    <?php 
	        $query1 = new WP_Query( 'category_name=front' );
	        $post_already_displayed = array();
	     ?>
		<?php if ( $query1->have_posts() ) : ?>

		<?php /* Start the Loop */ ?>
		<?php while ( $query1->have_posts() ) : $query1->the_post(); $post_already_displayed[] = get_the_ID(); ?>
		<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
			
			<header class="entry-header">
				<?php if ( ! post_password_required() && ! is_attachment() ) :
				the_post_thumbnail();
		    	endif; ?>

				
				<h1 class="entry-title">
					<a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?>
					</a>
					<?php the_date('Y-m-d', '<div class="published-date">Published at ', '</div>'); ?>
				</h1>
	
				<?php if ( comments_open() ) : ?>
				<div class="comments-link">
					<?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'twentytwelve' ) . '</span>', __( '1 Reply', 'twentytwelve' ), __( '% Replies', 'twentytwelve' ) ); ?>
				</div>
				<!-- .comments-link -->
				<?php endif; // comments_open() ?>
			</header>
			<!-- .entry-header -->

		
			<div class="entry-content">
				<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentytwelve' ) ); ?>
			</div>

		</article>
		<!-- #post -->
		<?php endwhile; ?>


		<?php endif; // end have_posts() check ?>
		<?php wp_reset_postdata();?>
		
		  <?php $query2 = new WP_Query(  array( 'post__not_in' => $post_already_displayed )); ?>
		<?php if ( $query1->have_posts() ) : ?>

		<?php /* Start the Loop */ ?>
		<?php while ( $query2->have_posts() ) : $query2->the_post(); ?>
		<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
			
			<header class="entry-header">
				<?php if ( ! post_password_required() && ! is_attachment() ) :
				the_post_thumbnail();
		    	endif; ?>

				
				<h1 class="entry-title">
					<a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?>
					</a>
					<?php the_date('Y-m-d', '<div class="published-date">Published at ', '</div>'); ?>
				</h1>
	
				<?php if ( comments_open() ) : ?>
				<div class="comments-link">
					<?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'twentytwelve' ) . '</span>', __( '1 Reply', 'twentytwelve' ), __( '% Replies', 'twentytwelve' ) ); ?>
				</div>
				<!-- .comments-link -->
				<?php endif; // comments_open() ?>
			</header>
			<!-- .entry-header -->

		
			<div class="entry-content">
				<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentytwelve' ) ); ?>
			</div>

		</article>
		<!-- #post -->
		<?php endwhile; ?>


		<?php endif; // end have_posts() check ?>
		<?php wp_reset_postdata();?>

	</div>
	<!-- #content -->
</div>
<!-- #primary —>

In the above code the first query fetches all the posts from the category front, then when we process through its loop we store the post ids of the posts displayed. In the second query we query for all posts which are not in the array which we stored in the first loop.

If we run the above loop the output will be all posts from category front on top as shown below.

image002

Using get_posts

In addition to the above, one can also use get_posts to fetch posts from WordPress. get_posts takes the same parameters as query_posts, but only takes them in the form of an array rather than a string. get_posts should be used when one needs to fetch posts statically for something such as a widget.

If we want to get all the posts which do not belong to category using get_posts, we can use the following code

//Cat_ID for category front is 4 .
$args = array( 'posts_per_page' => 5, 'category' => -4 );
$myposts = get_posts( $args );
foreach ( $myposts as $post ) {
    echo $post->post_title;
}

Using a Direct Database Query

Though I would not recommend querying the database directly, it is still useful to know that you can run raw SQL queries to fetch data. WordPress has a $wpdb object which can be used to run SQL queries on the WordPress DB. For example, you can use a query as shown below to fetch the first five posts and build a loop out of it to display data.

global $wpdb;
$results = $wpdb->get_results( "SELECT ID, post_title FROM $wpdb->posts WHERE ID < 5;" );
print_r( $results );

Conclusion

As WordPress sites have started being used for many different types of sites , the different requirements for displaying the posts are in huge number. The WordPress loop is extremely useful API which can be used on your site very effectively. Also, knowing the different ways in which the WordPress loop can be built will help one built sites with any requirements using WordPress. So have fun building your next WordPress loop.

Leave a Reply

Your email address will not be published. Required fields are marked *

Send this to friend