Languages: English • API/アクションフック一覧/pre get posts 日本語 Português do Brasil • (Add your language)
This hook is called after the query variable object is created, but before the actual query is run.
The pre_get_posts action gives developers access to the $query object by reference (any changes you make to $query are made directly to the original object - no return value is necessary).
<?php add_action( 'pre_get_posts', 'your_function_name' ); ?>
The $query object is passed to your function by reference. You do not need to declare globals or return a value. Any changes you make to the object from inside your function are made to the original immediately.
pre_get_posts should not be used to alter the query for single Page requests (page templates) because 'is_page', 'is_singular', 'pagename' and other properties (depending if pretty permalinks are used) are already set by the parse_query() method. See: Query Overview.
Similarly, pre_get_posts will not work if used in template files (e.g., archive.php), since they are called after the query has been completed.
Unless you are intimately familiar with these settings and are willing to coordinate them, it's suggested that you alter the main query for single page requests by using a new WP_Query in the page template itself.
You can check out the following post regarding the use of pre_get_posts on true pages and static front pages where we alter the pagination through pre_get_posts and the filters availble in the WP_Query class and using post injection in order to make pre_get_posts work
When using pre_get_posts, be aware of the query you are changing. One useful function is is_main_query(), which can help you ensure that the query you are modifying is only the main query. Use it in combination with other conditional tags to only alter the main query on the pages you want.
This filter can also be used to affect admin screen queries. Be sure to check if your modification is affecting your post edit screens. For example, just checking is_main_query() and is_post_type_archive('movie') will also change the query for the edit.php?post_type=movie admin screen, unless you also check for !is_admin()
pre_get_posts runs before WP_Query has been set up. Some template tags and conditional functions that rely on WP_Query will not work. For example, is_front_page() will not work, although is_home()will work. In such cases, you will need to work directly with the query vars, which are passed to the pre_get_posts hook as an argument ($query in examples on this page).
Using the offset argument in any WordPress query can break pagination. If you need to use offset and preserve pagination, please keep in mind that you will need to handle pagination manually. Read the codex article Making Custom Queries using Offset and Pagination for more information.
If WP_Query determines that the result will be singular (is_singular() is true), it will ignore the tax_query parameter. To modify tax_query, use the posts_clauses filter to add the required SQL statements.
This is how you can exclude categories of posts from displaying in your blog. For example, if you have 2 categories of posts (uncategorized '1' and another '1347') that you don't want to display on your 'home' blog page, you can use the following in your plugin or theme to omit these categories:
function exclude_category( $query ) { if ( $query->is_home() && $query->is_main_query() ) { $query->set( 'cat', '-1,-1347' ); } } add_action( 'pre_get_posts', 'exclude_category' );
Place this code in functions.php to cause the home page to display posts only from one category.
function my_home_category( $query ) { if ( $query->is_home() && $query->is_main_query() ) { $query->set( 'cat', '123' ); } } add_action( 'pre_get_posts', 'my_home_category' );
Change "123" to the category ID you wish to display.
Excludes an array of single post ID's from your home page
function exclude_single_posts_home($query) { if ($query->is_home() && $query->is_main_query()) { $query->set('post__not_in', array(7,11)); } } add_action('pre_get_posts', 'exclude_single_posts_home');
Often when readers of your blog search for something, it is most likely to be in posts rather than pages. So, you might like to exclude pages in your search results. It is possible to create an action hook that limits the search results by showing only results from posts.
The following example demonstrates how to do that:
function search_filter($query) { if ( !is_admin() && $query->is_main_query() ) { if ($query->is_search) { $query->set('post_type', 'post'); } } } add_action('pre_get_posts','search_filter');
function search_filter($query) { if ( !is_admin() && $query->is_main_query() ) { if ($query->is_search) { $query->set('post_type', array( 'post', 'movie' ) ); } } } add_action('pre_get_posts','search_filter');
Uses the date_query from WP_Query. In this example, only returns results after 1/1/2013
add_action( 'pre_get_posts', 'date_search_filter' ); function date_search_filter($query) { if ( ! is_admin() && $query->is_main_query() ) { if ($query->is_search) { $query->set( 'date_query', [ [ 'after' => 'January 1st, 2013', 'inclusive' => true, ] ] ); } } }
WordPress includes a single global setting for controlling the number of posts that appear on one loop page (under "Blog pages show at most" in the admin"). It is possible to create an action hook that changes / overrides the posts_per_page setting on a case-by-case basis. Best of all, this is done before the query is even executed (so there is no performance cost)!
The following example demonstrates how to override the page size ('posts_per_page') for archives of specific post types:
function hwl_home_pagesize( $query ) { if ( is_admin() || ! $query->is_main_query() ) return; if ( is_home() ) { // Display only 1 post for the original blog archive $query->set( 'posts_per_page', 1 ); return; } if ( is_post_type_archive( 'movie' ) ) { // Display 50 posts for a custom post type called 'movie' $query->set( 'posts_per_page', 50 ); return; } } add_action( 'pre_get_posts', 'hwl_home_pagesize', 1 );
You can override the number of posts to show up in a specific feed using the posts_per_rss setting.
function bdn_feed_set_posts_per_rss( $query ) { if( !$query->is_main_query() || !is_feed() ) return; //set conditional $query->set( 'posts_per_rss', 50 ); }
For reference, this is one possible example of the WP_Query object ($query) exposed by this hook. For more detail, you can also review the WP_Query codex page.
WP_Query Object ( [query_vars] => Array ( [page] => [pagename] => blog [error] => [m] => 0 [p] => 0 [post_parent] => [post_type] => [subpost] => [subpost_id] => [attachment] => [attachment_id] => 0 [name] => [static] => [page_id] => 0 [second] => [minute] => [hour] => [day] => 0 [monthnum] => 0 [year] => 0 [w] => 0 [category_name] => [tag] => [cat] => [tag_id] => [author_name] => [feed] => [tb] => [paged] => 0 [comments_popup] => [meta_key] => [meta_value] => [preview] => [s] => [sentence] => [fields] => [category__in] => Array ( ) [category__not_in] => Array ( ) [category__and] => Array ( ) [post__in] => Array ( ) [post__not_in] => Array ( ) [tag__in] => Array ( ) [tag__not_in] => Array ( ) [tag__and] => Array ( ) [tag_slug__in] => Array ( ) [tag_slug__and] => Array ( ) ) [tax_query] => [meta_query] => [post_count] => 0 [current_post] => -1 [in_the_loop] => [comment_count] => 0 [current_comment] => -1 [found_posts] => 0 [max_num_pages] => 0 [max_num_comment_pages] => 0 [is_single] => [is_preview] => [is_page] => [is_archive] => [is_date] => [is_year] => [is_month] => [is_day] => [is_time] => [is_author] => [is_category] => [is_tag] => [is_tax] => [is_search] => [is_feed] => [is_comment_feed] => [is_trackback] => [is_home] => 1 [is_404] => [is_comments_popup] => [is_paged] => [is_admin] => [is_attachment] => [is_singular] => [is_robots] => [is_posts_page] => 1 [is_post_type_archive] => [query_vars_hash] => 41032f87127fba65fb6743b1e97d8662 [query_vars_changed] => [thumbnails_cached] => [query] => Array ( [page] => [pagename] => blog ) [queried_object] => stdClass Object ( [ID] => 16 [post_author] => 1 [post_date] => 2012-01-31 17:23:57 [post_date_gmt] => 2012-01-31 17:23:57 [post_content] => [post_title] => Blog [post_excerpt] => [post_status] => publish [comment_status] => open [ping_status] => open [post_password] => [post_name] => blog [to_ping] => [pinged] => [post_modified] => 2012-01-31 17:23:57 [post_modified_gmt] => 2012-01-31 17:23:57 [post_content_filtered] => [post_parent] => 0 [guid] =>