WP_Query is a built-in class in WordPress for database interaction to get the list of posts based on supplied arguments.

WP_Query class is also used by functions like get_posts() and query_posts() but are implemented in different ways.

Using WP_Query is the most preferred method when you wanted to completely change the main query or if you wanted to create multiple queries within the same template. An example of this is when you wanted to add a list of recent posts after the content.

Standard Query (main query)

The example below is a standard loop used in single and page template. It uses the default query and global variable values.

<?php
   if(have_posts()) :
	while(have_posts()) : the_post(); ?>

         	<h1><?php the_title() ?></h1>
         	<div><?php the_content(); ?></div>

	<?php endwhile; ?>
<?php endif; ?>

You will notice that we used two (2) functions, have_posts() and the_post().

The have_posts() function uses the global $wp_query variable and checks to see if it has any results to loop over.

The the_post() function retrieves the next post, sets up the post data, and sets the ‘in the loop’ property to true.

Custom Query (using WP_Query)

The example below is a loop using new instance of WP_Query.

wp_reset_postdata() should be used after the loop to reset the global variables to the main query.

<?php
$args = array('post_type' => 'article');
$query = new WP_Query($args);
if($query->have_posts()) :
	while($query->have_posts()) : $query->the_post(); ?>

			<h1><?php the_title() ?></h1>
			<div><?php the_content(); ?></div>

	<?php endwhile; wp_reset_postdata(); ?>
<?php endif; ?>

In our above example, we created our object and store the results into the $query variable. We then check if it contains any results to loop by passing $query into the have_posts() function.

Multiple Queries

The example below shows how to use WP_Query to create multiple loops with completely different arguments.

<?php
//First WP_Query instance
$args1 = array('post_type' => 'article', 'posts_per_page' => 10);
$query1 = new WP_Query($args1);
if($query1->have_posts()) :
	while($query1->have_posts()) : $query1->the_post(); ?>

			<h1><?php the_title() ?></h1>
			<div><?php the_content(); ?></div>

	<?php endwhile; wp_reset_postdata(); ?>
<?php endif; ?>

<?php
//Second WP_Query instance
$args2 = array('post_type' => 'members', 'posts_per_page' => 5, 'order' => 'DESC');
$query2 = new WP_Query($args2);
if($query2->have_posts()) : ?>
	<ul>
		<?php while($query2->have_posts()) : $query2->the_post(); ?>

			<li><?php the_title(); ?></li>

		<?php endwhile; wp_reset_postdata(); ?>
	</ul>
<?php endif; ?>

Security

WP_Query is the most preferred and secured way of interacting into the database. The query is using MySQLi prepared statement in addition to the filters applied to the query strings.