Redirect old URL (with different post ID) to new URL

Note: The suggested method will be updated from time to time after collecting more information from the asker. The current suggested method assumed some conditions.

  • The following code is for putting in functions.php, if you are writing a plugin. Please remember to change the callback and write in plugin mode. For more about plugin writing, please refer to Plugin Handbook

This example is assumed

  • the site domain is changed
  • the whole url structure is same, if not, then this solution is not suitable

Case 1

If you have an old site, and want to redirect any page to new site with just difference domain name. You may try this

add_action( 'init', 'q363843_global_redirect' );
function q363843_global_redirect() {
    // do redirect before sending header
    if ( isset( $_SERVER['HTTP_HOST'] ) ) {
        $requested_url  = is_ssl() ? 'https://' : 'http://';
        $requested_url .= $_SERVER['HTTP_HOST'];
        $requested_url .= $_SERVER['REQUEST_URI'];
    }
    
    // @ means surpass warning, for it is used in WordPress Core file like canonical.php, so I follow, for development, it is better to leave it
    //  $original = @parse_url( $requested_url );
    $original = parse_url( $requested_url );
    
    // change only domain, assume the new site is same in structure
    // 'something-else' must be different host for same host, an over simplified redirect without well checking will result in redirect loop, so beware
    wp_redirect( $original['scheme'] . '://' . 'something-else' . $original['path'] );

    // exit will terminate the script immediately after redirect is called,
    // this will ensure that the current script will be stopped here and prevent from infinite loop
    // if use return here, it means finish the function but script is possible to continue in some occasions...
    exit();
}

importantance of exit()
Putting exit() after redirect is WordPress Core practice used in such as canonical.php, ms-functions.php, pluggable.php and you name it.

...Terminates execution of the script...

about return keyword

...return returns program control to the calling module.

Case 2

If you want to check the post-name of the site, you may consider the following, it is similar to case 1, only that you need to check the post-name.

This is one of the possibilities, mechanism:

  • (Old site) do the redirect first
  • because the new site is of different structure, just redirect to http://new-domain.com/post-name first
  • (New site) use query hook or pre_get_posts to analyse and get the right post id. query filter is one of the earliest filters that handle the query. Together with the help of url_to_postid, you can find the post id from the redirect link.

My personal worked experience and preference, I choose query filter and rebuild the query. The reason to use query because

  • it manipulates the query before putting into $wp_query, so there is no $post is created yet, the global $post at this point is null.
  • it is before any 404 being check and set
  • if set it right and understand it, I could resolve any 404 issue.

Assumption:

  • post-name exist in both side and remain the same
// In the old site functions.php
add_action( 'init', 'q363843_global_redirect' );
function q363843_global_redirect() {
    // do redirect before sending header
    if ( isset( $_SERVER['HTTP_HOST'] ) ) {
        $requested_url  = is_ssl() ? 'https://' : 'http://';
        $requested_url .= $_SERVER['HTTP_HOST'];
        $requested_url .= $_SERVER['REQUEST_URI'];
    }
    
    $original = parse_url( $requested_url );

    // your extract post-name mechanism

    $redirect = $original['scheme'] . '://' . 'new-domain' . '/post-type/post-name'; // <-- add post type if you know it, increase the matching possibility for url_to_postid()

    wp_redirect( $redirect );

    exit();
}
// In the new site functions.php
add_filter( 'query', 'q363851_check_query_from_url');
function q363851_check_query_from_url( $query ) {
   // check and build the URL
   if ( isset( $_SERVER['HTTP_HOST'] ) ) {
        $requested_url  = is_ssl() ? 'https://' : 'http://';
        $requested_url .= $_SERVER['HTTP_HOST'];
        $requested_url .= $_SERVER['REQUEST_URI'];
    }

    // try to fetch post id using built-in function
    $post = url_to_postid( $requested_url );

    var_dump($post); // check to see
    
    // here, you could either build the URL, redirect and exit this script (lazier) OR
    // you modify the query so that WordPress think that the post type and page id is valid for next step

    return $query;
}