Paulund
2013-03-18 #wordpress

How To Create Custom Queries In Wordpress

All the data you enter into Wordpress will get stored in the database, depending on what page you are on Wordpress will query the database in a different way. If you are on the index page then Wordpress will query the database to get the latest posts, if you are on the category pages then Wordpress will return the latest posts in that category, if you are on the single page then Wordpress will return this one post. But you can change the SQL call to query the database for any information that you want. There are many ways you can query the Wordpress database, here we are going over 3 different ways pre_get_posts action, query_posts() function or the WP_Query class.

The pre_get_posts Action

When you make a query to the database Wordpress creates a global variable called $query. By using the action pre_get_posts you can get access to this $query variable as a parameter to the callback function. From inside this callback function you can modify it before it makes a call to the database. Be aware that this action it's used on all calls to the database which includes calls inside the admin area, it could also be called multiple times which is why it's important to check if the call you are modifying is the main query and you are on the page you are expecting. To check if you are changing the main query you can use the function is_main_query().


if(is_main_query())
{
     // Modify the query
}

But as this can also be called from the admin area so you need to also check that you are on the page you are expecting, for example if you want to change the category query you need to also use the is_category() function.


if(is_main_query() && is_category())
{
     // Modify the query
}

For example if you want to exclude a category from the index page query then you can modify the query with this call.


add_action( 'pre_get_posts', 'exclude_category' );
function exclude_category( $query ) {
    if ( $query->is_home() && $query->is_main_query() && ! $query->get( 'cat' ) ){
        $query->set( 'cat', '-5' );
    }
}

You can change the number of posts you get back from the query by changing the parameter posts_per_page.


add_action( 'pre_get_posts', 'get_one_post' );
function get_one_post( $query ) {
    if ( $query->is_home() && $query->is_main_query() ){
        $query->set( 'posts_per_page', 1 );
    }
}

The pre_get_posts action should be used when you just need to modify the existing query used by Wordpress, if you need to make additional queries then you should be using the WP_Query class. pre_get_posts

query_posts Function

The query_posts function is another way of editing the main query in Wordpress, this is the simplest way of editing the query to the database as it will override the $query variable. Though this is the simplest way of editing the main query it is not the preferred method or the most efficient, it is better to use the pre_get_post action and modify the main query. Just like the pre_get_post action you can use the query_post function to change the number of posts that are returned, by default Wordpress will return 10 posts if you want to change this to 1 post you can use this code.


<?php

query_posts( 'posts_per_page=1' );

while ( have_posts() ) : the_post();
    echo '<h1>';
    the_title();
    echo '</h1>';
endwhile;
?>

Query_posts() Function

WP_Query Class

The WP_Query class is defined in wp-includes/query.php and is the class that is used to make queries to the database to get the posts we need for a certain page. The WP_Query class will create a variable which can be used anywhere on the page, the variable is $wp_query and has a number of methods which can be used to get information from the query. The main methods that you may already be aware of is the $wp_query->have_posts() method which is called from within the loop by the have_posts() function. You can also use this variable inside The Loop by getting the information for the current post by using the the_post() method. If you are using the WP_Query class to modify the Wordpress query then you need to use the variable of the class to call the have_posts() methods and the the_post() method.


$new_query = new WP_Query( $args );

// The Loop
while ( $new_query->have_posts() ) :
    $new_query->the_post();
    printf('<h1>%s</h1>', get_the_title() );
endwhile;

The WP_Query class can be used to make a secondary call to the database, but if you want to make a new call then you need to reset the previous query call by using the function wp_reset_postdata().


$new_query = new WP_Query( $args );

// The Loop
while ( $new_query->have_posts() ) :
    $new_query->the_post();
    printf('<h1>%s</h1>', get_the_title() );
endwhile;

wp_reset_postdata(); $second_query = new WP_Query( $second_args ); // The Loop while ( $second_query->have_posts() ) : $second_query->the_post(); printf('# %s

', get_the_title() ); endwhile; wp_reset_postdata(); There are a number of different parameters and methods that you can use with the WP_Query class there is a list of all of them on the Wordpress codex. Methods And Properties## Example Queries With WP_Query

Get Posts By Author


$query = new WP_Query( 'author=' . $author_id );

Exclude Posts By Author


$query = new WP_Query( 'author=-' . $author_id );

Get Posts In A Certain Category


$query = new WP_Query( 'cat=' . $category_id );

Exclude Posts In A Certain Category


$query = new WP_Query( 'cat=-' . $category_id );

Get Posts In A Tag


$query = new WP_Query( 'tag=' . $tag_name );

Get Posts In Certain Taxonomy


$args = array(
    'post_type' => 'post',
    'custom_tax' => 'term'
);
$query = new WP_Query( $args );

Get Posts From Search Terms


$query = new WP_Query( 's=' . $search_term );

Get Post By Post ID


$query = new WP_Query( 'p=' .$post_id );

Get Post By Post Slug


$query = new WP_Query( 'name=' . $post_slug );

Get All Posts


$query = new WP_Query( 'posts_per_page=-1' );

Get A Random Post


$query = new WP_Query( array ( 'orderby' => 'rand', 'posts_per_page' => '1' ) );

Get Posts By Most Comments


$query = new WP_Query( array( 'orderby' => 'comment_count' ) );