pre_get_posts
云策文档标注
概述
pre_get_posts 是一个 WordPress 动作钩子,在查询变量对象创建后、实际查询运行前触发,允许开发者修改 WP_Query 实例以定制查询行为。文档重点介绍了如何正确使用条件标签来定位目标查询,避免意外影响其他查询,并提供了多个代码示例。
关键要点
- pre_get_posts 钩子在 WP_Query 实例创建后、查询执行前触发,用于修改查询参数。
- 使用条件标签(如 $query->is_main_query() 和 is_admin())来精准定位目标查询,避免影响后台查询或自定义循环。
- 注意 pre_get_posts 运行时 WP_Query 尚未完全设置,某些依赖 WP_Query 的条件函数(如 is_front_page())可能无效,需直接操作查询变量。
- 使用 offset 参数可能破坏分页,需要手动处理分页逻辑。
- 主查询已有默认属性设置,修改查询类型(如单篇文章到归档)需重置查询对象属性,或直接在主题模板中使用 WP_Query 替换。
代码示例
// 示例:针对分类归档的主查询修改每页文章数
function target_main_category_query_with_conditional_tags( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
if ( is_category() ) {
$query->set( 'posts_per_page', 15 );
}
}
}
add_action( 'pre_get_posts', 'target_main_category_query_with_conditional_tags' );
// 示例:从首页排除特定文章ID
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' );
// 示例:在搜索结果中仅显示特定日期后的文章
function date_search_filter($query) {
if ( ! is_admin() && $query->is_main_query() ) {
if ( $query->is_search ) {
$query->set( 'date_query', array(
array(
'after' => 'May 17, 2019',
)
) );
}
}
}
add_action( 'pre_get_posts', 'date_search_filter' );注意事项
- 避免在 pre_get_posts 中使用全局条件函数如 is_main_query(),应使用 $query->is_main_query() 方法。
- 修改查询时需谨慎,确保不影响后台管理界面或其他非目标查询。
- 处理分页和偏移量时,需参考相关文档进行手动管理。
原文内容
Fires after the query variable object is created, but before the actual query is run.
Description
Note: If using conditional tags, use the method versions within the passed instance (e.g. $this->is_main_query() instead of is_main_query() ). This is because the functions like is_main_query() test against the global $wp_query instance, not the passed one.
Parameters
Source
do_action_ref_array( 'pre_get_posts', array( &$this ) );
Changelog
| Version | Description |
|---|---|
| 2.0.0 | Introduced. |
Skip to note 8 content
saddamcrr7
Example for how to universally adjust queries for an ‘event’ post type:
function university_adjust_queries($query){ if ( ! is_admin() && is_post_type_archive( 'event' ) && $query->is_main_query() ) { $query->set( 'meta_key', 'event_date' ); $query->set( 'orderby', 'meta_value_num' ); $query->set( 'order', 'ASC'); $query->set( 'meta_query', array( array( 'key' => 'event_date', 'compare' => '>=', 'value' => date('Ymd'), 'type' => 'numeric', ) ) ); } } add_action( 'pre_get_posts', 'university_adjust_queries' );Skip to note 9 content
seabluetom
/** * * The Code below will modify the main WordPress loop, before the queries fired, * to only show posts in the halloween category on the home page. * */ function wpdocs_exclude_category( $query ) { if ( $query->is_home() && $query->is_main_query() && ! is_admin() ) { $query->set( 'category_name', 'halloween' ); } } add_action( 'pre_get_posts', 'wpdocs_exclude_category' );Skip to note 10 content
johnjullies
Include Custom Post Types in the homepage
function add_custom_pt( $query ) { if ( !is_admin() && $query->is_main_query() ) { $query->set( 'post_type', array( 'post', 'the_custom_pt' ) ); } } add_action( 'pre_get_posts', 'add_custom_pt' );Include in Search Results
function add_custom_pt( $query ) { if ( !is_admin() && $query->is_main_query() ) { if ( $query->is_search ) { $query->set( 'post_type', array( 'post', 'the_custom_pt' ) ); } } } add_action( 'pre_get_posts', 'add_custom_pt' );Replace ‘the_custom_pt’ with the name of your custom post type.
Skip to note 11 content
capbussat
You can filter posts or pages from ‘Recent Posts’ or other widgets that do not contain a meta key. In this example ‘transk_lang’ is a language meta key assigned to posts and pages.
add_action( 'pre_get_posts', 'wpdocs_pre_get_posts' ); function wpdocs_pre_get_posts( $query ) { // avoid main query if ( $query->is_main_query() ) { return; } // avoid filtering menu items if ( 'nav_menu_item' === $query->query_vars['post_type'] ) { return; } // add meta query $meta_query = $query->get( 'meta_query' ); if ( ! is_array( $meta_query ) ) { $meta_query = array(); } $meta_query[] = array( 'key' => 'transk_lang', 'value' => get_user_locale(), 'compare' => '==', ); $query->set( 'meta_query', $meta_query ); }Skip to note 12 content
Joseph Harburg
If you want to use URL parameters to alter the search query and search for custom meta that returns a single item:
e.g. https://site.com/?s=searchTerm&single;_custom_meta=value
add_action( 'pre_get_posts', 'wpdocs_url_search_modifications' ); function wpdocs_url_search_modifications( $query ) { if ( $query->is_search && ! is_admin() ) { if ( isset($_GET['single_custom_meta'] ) ) { $query->set( 'meta_key', 'single_custom_meta' ); $query->set( 'meta_value', sanitize_text_field( $_GET['single_custom_meta'] ) ); } } return $query; }If you need to use a comma-delineated list of terms to search for multiple terms with custom meta that returns an array.
e.g. https://site.com/?s=searchTerm&multiple;_custom_meta=valueone,valuetwo
add_action( 'pre_get_posts', 'wpdocs_url_search_modifications' ); function wpdocs_url_search_modifications( $query ) { if ( $query->is_search && ! is_admin() ) { if ( isset( $_GET['multiple_custom_meta'] ) ) { // Make our query string an array $multiple_custom_meta_values = explode( ',', sanitize_text_field( $_GET['multiple_custom_meta'] ) ); // Generate the meta query array you can change this to your liking $meta_query_array = array( 'relation' => 'OR' ); // Add a query for each item in our list foreach ( $multiple_custom_meta_values as $key => $value ) { $meta_query_array[] = array( 'key' => 'multiple_custom_meta', 'value' => $value, 'compare' => 'LIKE' ); } //set the meta query $query->set( 'meta_query', $meta_query_array ); } }; return $query; }Skip to note 13 content
Chigozie Orunta
This example helps you to exclude specific categories using their IDs. You can replace the IDs 1, 2, & 3 with the specific category IDs you want to exclude.
add_action( 'pre_get_posts', 'wpdocs_exclude_categories' ); function wpdocs_exclude_categories( $query ) { if ( is_admin() ) { return; } if ( ! $query->is_home() || ! $query->is_main_query() ) { return; } $query->set( 'cat', '-1,-2,-3' ); }Skip to note 14 content
thejaydip
/**
* Exclude all sticky posts from the archive.
*
* @param WP_Query $query Query.
*/
function wpdocs_exclude_sticky_posts_from_archive( $query ) {
if ( $query->is_main_query() && ! is_admin() && $query->is_archive() ) {
$sticky_posts = get_option( ‘sticky_posts’ );
if ( ! empty( $sticky_posts ) ) {
$query->set( ‘post__not_in’, $sticky_posts );
}
}
}
add_action( ‘pre_get_posts’, ‘wpdocs_exclude_sticky_posts_from_archive’ );