0

I recently merged two websites. So all the posts of 'old website' were migrated to 'new website'. Now I want the old URL's to redirect to the new URL's. My first choice was a .htaccess rewrite, but this isn't possible because the URL's have a different post ID.

Old website: https://oldwebsite.com/category/1000/hello-world New website: https://newwebsite.com/category/2000/hello-world

So in fact, I would have to match the URL's by post name. WordPress should then automatically check which post on the new website has the same title, and redirect to that post.

How can I do that?

Many thanks in advance!

UPDATE: The setup is actually quite simple. It are two different single WordPress installations. I now want to redirect all the links of the old site to the new site, but the problem is that the post ID is different for every post, so I can't simply replace the domain in the URL and be done with it.

3
  • So you will keep the old site and plan to modify the old site for redirection? Any specific conditions like post only or anything? – simongcc Apr 12 '20 at 12:01
  • I have suggested a generic way for whole site first. If in the new site, the structure is a bit different. Then you better describe more to us so that we could provide more accurate solutions. – simongcc Apr 12 '20 at 12:16
  • Can you clarify what the current setup is? Do you mean you have 2 installs, and you need to change the old install to redirect to the new one? Or is this a multisite? Or is a single site handling both domains with posts for both sites in the same install listed alongside eachother? It's unclear, use the edit link under the question to add this information to your question. Right now it's not possible to answer with just the information available – Tom J Nowell Apr 12 '20 at 12:35
1

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;
}
9
  • 1
    Can you update the answer to explain how it works? Copy pasta doesn't help if the asker needs to make a modification, or if someone else has a similar issue but doesn't understand the answer. Also, there's an @ operator in your code, this should be avoided at all costs and is bad practice. @ doesn't stop errors, it just silences them in the logs. Instead, check if parse_url returned false and handle the failure. Additionally, because this always runs on the init hook, and there are no return statements, all pages will redirect, leading to infinite redirect loops – Tom J Nowell Apr 12 '20 at 12:30
  • @TomJNowell Ok I will update later after collecting more information. And sorry for the @ sign since I have referred to WordPress core source code in canonical.php which I know it surpass warning. And about the return problem, because there is an exit() at the end, if leave the exit(), loop might be occur. Anyway, I will add some more explanation later and maybe add some other alternatives after collecting more information to the practical situation. Thanks for your long comment and concerns which help and benefit a lot. – simongcc Apr 12 '20 at 12:38
  • 1
    @TomJNowell I have updated explanations including the @ mark, difference between return and exit() and why exit() is used rather than return. Thanks again for your idea. I have also updated other answers which will definitely benefit more audience. – simongcc Apr 13 '20 at 6:29
  • Thanks, I like that you laid out the assumptions and taught why exit is needed, upvoted – Tom J Nowell Apr 13 '20 at 10:05
  • Thanks for your appreciation and your sharing too. :) – simongcc Apr 13 '20 at 10:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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