I recently dramatically changed the structure of my site and I’m getting errors from pages that existed on the past (and they will probably) exist on the future again.

eg:

in the past I had 44 pages (example.com/manual-cat/how-to/page/44/) and right now I only have posts to have 39 pages, but I will probably have more pages in the future.

How can I temporarily redirect ONLY if the page doesn’t exists?

The reason I need to do this automatically is that I have 100 plus categories with errors and it would be impossible to manage this manually by doing individual redirects.

If this had to be done on the server side, please be aware that I’m on nginx.

3 Answers
3

You can detect non-existent pages only with WordPress. Normal URLs don’t point to a physical resource, their path is mapped internally to database content instead.

That means you need a WP hook that fires only when no content has been found for an URL. That hook is 404_template. This is called when WP trys to include the 404 template from your theme (or the index.php if there is no 404.php).

You can use it for redirects, because no output has been sent at this time.

Create a custom plugin, and add your redirection rules in that.

Here is an example:

<?php # -*- coding: utf-8 -*-
/**
 * Plugin Name: Custom Redirects
 */

add_filter( '404_template', function( $template ) {

    $request = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_STRING );

    if ( ! $request ) {
        return $template;
    }

    $static = [
        '/old/path/1/' => 'new/path/1/',
        '/old/path/2/' => 'new/path/2/',
        '/old/path/3/' => 'new/path/3/',
    ];

    if ( isset ( $static[ $request ] ) ) {
        wp_redirect( $static[ $request ], 301 );
        exit;
    }

    $regex = [
        '/pattern/1/(\d+)/'    => '/target/1/$1/',
        '/pattern/2/([a-z]+)/' => '/target/2/$1/',
    ];

    foreach( $regex as $pattern => $replacement ) {
        if ( ! preg_match( $pattern, $request ) ) {
            continue;
        }

        $url = preg_replace( $pattern, $replacement, $request );
        wp_redirect( $url, 301 );
        exit;
    }

    // not our business, let WP do the rest.
    return $template;

}, -4000 ); // hook in quite early

You are of course not limited to a simple map. I have versions of that plugin with quite some very complex for some clients, and you could even build an UI to create that map in the admin backend … but in most cases, this simple approach will do what you want.

Leave a Reply

Your email address will not be published. Required fields are marked *