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 ) );
exit();
}
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
}
}