The main query in a WordPress site is the query based on the URL being accessed. When you access this post’s single page, the URL indicates the main query is the text you are reading right now. The “Recent Posts” widget on the sidebar is generated from a query, but not the main query.
There are a few methods to test for the “main query”. As of WordPress 3.3, there is a new way:
$query->is_main_query()
Examples: Using pre_get_posts hook | Using posts_where hook
There’s the old way (which is the basis for the above method):
1 2 |
global $wp_the_query; if( $wp_the_query === $query) |
In situations where I wanted to alter the content of a post (in the loop) if it was the main query, the above methods didn’t work reliably. I attempted to hook into the pre_get_posts action and set a global variable, which I would then test in the content filter function. I reasoned that the variable would be set to true before the loop, and then set to false if another query was called after that. The results however were always false.
My solution was to set a global variable with the post ID in a wp_head action, then test that against the post ID while in the loop (every time the_content filter is called.) Code below…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
add_action( 'wp_head', 'main_query_test', 0 ); function main_query_test() { global $main_query_test, $post; $main_query_test = $post->ID; } add_filter('the_content', 'my_content_filter'); function my_content_filter($content) { global $main_query_test; if ($main_query_test == get_the_id() && is_singular()) { $main_query_test = null; // Prevent a second instance // do content filtering } return $content; } |
Now it’s quite possible this is not the most direct, efficient or reliable method. I welcome your comments if you have suggestions or concerns.