I'm trying to alter the main query when a single page is being displayed, to return another page instead. I thought this was one of the few cases where query_posts() to permanently alter the main query would be fitting, but I still get the original post ID in many cases where I perform get_the_ID() and such.

What would be the right moment (action hook) and method to achieve this seemingly simple page request alteration?

Example: Whenever page ID 5 is requested, load page ID 10 instead.

  • do you mean with a redirect or keeping the same slug? Can you elaborate on why you need this?
    – birgire
    Sep 11, 2017 at 14:00
  • @birgire Without a redirect. It is indeed to use the slug of one page for another page under certain conditions.
    – Berend
    Sep 11, 2017 at 18:19

1 Answer 1


If you can access the ID of your post, it means that the query has already been run. So, in this case, you can't use pre_get_posts anymore.

A solution would be to wrap your code in a conditional, and then use functions such as get_the_permalink() or get_the_title() which accept a post ID, to get the content for another post:

if( get_the_ID() == '5' ){
    get_the_title( 10 );
} else {
    // Main loop

The above should be used in your templates.

Another reasonable and better approach would be to use redirection. Check the post's ID, and then redirect the user if the conditional matches:

if( get_the_ID() == '5' ) {
    wp_safe_redirect( get_the_permalink( 10 ) );

This can be used either in functions.php or the header of your templates.

There's also a hack you might want to use, to get pre_get_posts to work.

add_action( 'pre_get_posts', 'my_function' );
function my_function( $query ) {
    // Remove this action hook so we don't go into an infinite loop
    remove_action( 'pre_get_posts', 'my_function' );
    // Get a list of posts belonging to this query
    $posts = get_posts( $query->query );
    // If there is only one post in the array and its ID matches
    // what we're looking for, then we can alter the main query
    if( $query->is_main_query() && sizeOf( $posts ) == '1' && $post[0]->ID == '5' ) {
        // Now we can modify the query here
  • Since I really needed the entire page page to 'think' it is the other page, I went with something based on the third snippet in this answer. It first analyses $query to determine which post it's going to be, then alters the query to replace and remove values resulting in loading the new post instead.
    – Berend
    Sep 17, 2017 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.