2

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

6

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.

8
  • I didn't know there is a function called 404_template, in wp core... thanks! That being said, I guess (I'm not an expert in php) that $map is an array where I can also include a regular expression like this /old/path/page/[0-9]+?(/+)?$#'/ => /old/path/page/1/ ?
    – bpy
    Commented Apr 17, 2017 at 0:39
  • @Alex It's a hook, not a function. :) Yes, you can also use regular expressions, but then you have to use preg_match(), not a simple isset().
    – fuxia
    Commented Apr 17, 2017 at 0:41
  • ...oh, ok! How can I use preg_match() to check if page doesn't exists today?
    – bpy
    Commented Apr 17, 2017 at 1:16
  • @Alex I have added an example with regular expressions to my sample code.
    – fuxia
    Commented Apr 17, 2017 at 1:25
  • I admit that I'm having difficulties to handle this, but your help is from great value to me. I will post the end result. Thanks!
    – bpy
    Commented Apr 17, 2017 at 1:30
0

In your .htaccess try:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]

RewriteRule ^match/this/(.*)$ somewhere/else/$1 [L]
</IfModule>

So if it doesn't hit a file or a directory it will go to the rewrite rule at the bottom.

For nginx:

# nginx configuration
location / {
if (-e $request_filename){
rewrite ^/match/this/(.*)$ /somewhere/else/$1 break;
}
}
2
  • I'm on nginx so this code wont work.
    – bpy
    Commented Apr 17, 2017 at 0:07
  • I added the nginx version. Commented Apr 17, 2017 at 1:50
-1

You can use and edit .htaccess file

# Redirect old file path to new file path
Redirect /manual-cat/how-to/page/44/ http://example.com/newdirectory/newfile.html
1
  • This must be done automatically. I edited the question above.
    – bpy
    Commented Apr 16, 2017 at 23:31

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.