query_posts()
WordPress is used when retrieving posts for the current page (author archive, single post, category, tag).
query_posts() is a way to modify the main WordPress query that is created to display content on the page. This is achieved by replacing the main query (another query is made and replaces the main one).
This is important!
Although the function is simple to use, it is better not to use it because it has many potential issues, more details here: Using query_posts() is dangerous
Using this function can increase page load time (sometimes doubling it, because another query is made on top of the main one).
This function completely overrides the main query and is therefore not intended for use in plugins or themes.
For regular queries, use get_posts() or WP_Query - if pagination is needed.
To restore the main query back, after calling query_posts, you need to call wp_reset_query().
No Hooks.
Returns
WP_Post[]|Int[]. Global object WP_Query.
Usage
The query_posts() function should be called before the WordPress Loop, because when query_posts() is called, a new WP_Query object is created, which will then be used in the loop. At this point, WordPress ignores parameters received via the URL (for example, page number or category):
<?php
query_posts( $query );
// WordPress Loop
if( have_posts() ){
while( have_posts() ){
the_post();
}
wp_reset_query();
} else {
// text if there are no posts
}
?>
- $query(array|string) (required)
Massive or string of query parameters. A list of possible keys can be found in WP_Query.
This function can accept a variety of parameters, which can be specified as either an array or a string:
cat=4&posts_per_page=5.WP_Query underlies query_posts(), so it can receive all the same parameters.
Alternative
To modify the main query, it is strongly recommended to use the pre_get_posts event with a check for is_main_query().
Example: instead of
query_posts('posts_per_page=5');
use in functions.php:
add_action( 'pre_get_posts', 'five_posts_on_homepage' );
function five_posts_on_homepage( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'posts_per_page', 5 );
}
}
To modify the SQL query, you can use these filters.
Warnings
Modifies the main loop
query_posts() replaces the main query, affecting global variables and template tags, which may not work correctly after query_posts().
If query_posts() is used in a template, WordPress has already made the main query to the database. Using query_posts() means a repeated SQL query, ignoring the results of the previous one. This can be inefficient on large sites.
Secondary loops
For secondary lists (for example, related posts at the bottom of the page or links in the sidebar), it is better to use get_posts(). If you still use query_posts(), be sure to call wp_reset_query() after completion.
Pagination
Pagination will not work correctly without the proper setting of the paged parameter.
Additional SQL queries
Developers of large sites should consider alternatives, such as the request filter to modify the query before it is executed, or the parse_query and pre_get_posts filters to edit the $query object.
Additional info
Preserve existing query parameters
After calling query_posts(), WordPress will not consider parameters received via the URL (for example, page number or categories). If you need to preserve the parameters of the main query, you can use the global variable $query_string (which contains the current parameters for query_posts).
For example, let's change the sorting order of posts without affecting the other query parameters, for this you need to write the following code before the WordPress Loop:
global $query_string; query_posts( $query_string . '&order=ASC' );
In this example, the "batch" of additional arguments should be implemented with the ampersand sign (&)
You can also pass parameters as an array. To do this, merge the base parameters and our custom ones:
global $wp_query; $custom_params = [ 'post_type' => 'product' ]; $args = array_merge( $wp_query->query_vars, $custom_params ); query_posts( $args );
Combining parameters
#1. Combining in a string
You probably noticed that parameters are combined with the ampersand symbol - &, this is the symbol with which parameters are combined (merged).
query_posts( 'cat=3&year=2004' );
Get posts from category 1, having the tag apples:
query_posts( 'cat=1&tag=apples' );
#2. Combining with variables
Posts from category 13 for the current month on the blog homepage:
if ( is_home() ) {
query_posts( $query_string . '&cat=13&monthnum=' . date( 'n', current_time('timestamp') ) );
}
#3. Combining with an array
Will return only 2 posts, from categories 1 and 3, sorted in reverse order by title:
query_posts( [ 'category__and' => [ 1, 3 ], 'posts_per_page' => 2, 'orderby' => 'title', 'order' => 'DESC', ] );
Examples
#1 Get only the first part of the content $more = 0
If you want to use the "read more" function with a new query, you must switch the global variable $more to 0:
<?php
// retrieve one post with an ID of 5
query_posts('p=5');
global $more;
// set $more to 0 in order to only get the first part of the post
$more = 0;
// the Loop
while ( have_posts() ) {
the_post();
// the content of the post
the_content( 'Read the full post »' );
}
?> #2 Passing parameters in an array
Parameters can also be passed as an array. This makes them clearer and more readable.
query_posts( [ 'cat' => 22, 'year' => $current_year, 'monthnum' => $current_month, 'order' => 'ASC', ] );
As you can see, you can put each variable on a separate line here, and this is clearer and more readable.
#3 Exclude the posts from category 3, On the home page.
It's better to use pre_get_posts hook for this purpose.
To exclude posts that are in category 3 on the home page of your blog, you need to insert the following code in the front-page.php or home.php template files before you start the WordPress Loop:
Override the main query with all posts in a specific category:
if ( is_home() ) {
query_posts( 'cat=-3' );
}
You can add more categories to the exclusion:
if ( is_home() ) {
query_posts( "cat=-1,-2,-3" );
} #4 Passing variables into query parameters
You can create dynamic query parameters, if you want the query to change depending on the circumstances, write the value of the parameter to a variable and then pass the variable to the query parameters, you can do this in several ways:
1) Assembling a query using single quotes ' ':
<?php $category_var = $cat; // set the $category_var variable to the ID of the current category $query = 'cat=' . $category_var . '&orderby=date&order=ASC'; // assemble the query query_posts( $query ); // run a query to the database ?>
2) Assembling a query using double quotes ""
Variables inside double quotes are interpreted by PHP as variables, not plain text:
<?php
$current_month = date('m');
$current_year = date('Y');
query_posts( "cat=22&year=$current_year&monthnum=$current_month&order=ASC" );
?>
<!--here comes the WordPress Cycle -->
3) Using the global variable $query_string
Which contains the basic query for the query_posts() function. If we want to keep the standard output of WordPress posts (e.g. on a category page) but remove pagination (display all posts on one page), we can add the posts_per_page=-1 parameter to the basic query_posts function:
<?php
global $wp_query;
$wp_query = new WP_Query( $query_string . '&posts_per_page=-1' );
while( have_posts() ){
the_post();
// here comes the WordPress Cycle
}
wp_reset_query(); // reset global $wp_query
?>
We can measure the value of posts_per_page by the specific (int) posts we need on one page. For example, posts_per_page=10 will display only 10 posts, but if you put a template tag posts_nav_link() at the end of the loop, a link to go to the next 10 posts (pagination link) will appear below the loop.
4) Adding parameters to the query
Saving the basic query of the current page and adding your own parameters to it.
the query_posts() function completely rewrites the query, if for example we write query_posts ('cat=1'), other query parameters that are used for the current page (like sorting, pagination, etc.) will be lost and category 1 posts will be displayed with the other DEFAULT parameters.
To keep the basic query parameters and supplement/replace them with your own, use the PHP function array_merge() (merges 2 arrays into one):
global $wp_query; query_posts( array_merge( ['cat' => 1 ], // this is the parameter we added $wp_query->query // this is an array of basic query of the current page ) );
This example is essentially the same as the one using the global variable $query_string, only as an array.
#5 Change posts_per_page parameter for specific category
The “Blog pages show at most” parameter in Settings > Reading can influence your results. To overcome this, add the posts_per_page parameter. For example:
// if this request is for 'category-slug' category change number of posts
if ( is_category( 'category-slug' ) ) {
query_posts( [
'posts_per_page' => 999
] );
}
Use this code in the category.php template file.
See is_category().
#6 Get a specific post/page by ID or slug
It's not recommended to use query_posts() for this purpose, use get_posts() or get_post() instead.
Get a single post (with ID = 5):
<?php
// retrieve one post with an ID of 5
query_posts('p=5');
?>
Get a single page with ID 7:
<?php query_posts( 'page_id=7' ); ?>
Get a single page by it's slug:
<?php query_posts( 'pagename=about-site' ); ?>
Retrieving a child page.
For child pages, you must specify the name of the parent page and the child page itself. The names are separated by a slash (/). Example:
<?php query_posts( 'pagename=about-site/authors' ); // get the "authors" page, which is a child of "about-site" ?>
Notes
- Global. WP_Query.
$wp_queryWordPress Query object.
Changelog
| Since 1.5.0 | Introduced. |
query_posts() query posts code WP 7.0
function query_posts( $query ) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query( $query );
}