Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have an old website that I'm revamping with a custom new Wordpress theme. The old site had a custom (non-WP based) downloads archive that mapped URLs like this:

/downloads/view.php?id=2

The ID maps to a download item in a separate MySQL database.

I'd like to move everything over to Wordpress in this refresh and I'm going to be using a custom post type to handle the downloads section, with a custom field that maps the "old ID" to the new post. This isn't difficult and I know how to do this, but the issue becomes remapping the old URLs to the new locations.

The issue I see is that the older URLs are all PHP files (have an extension of .php). How would I go about create a plugin or Wordpress function in my theme's functions.php file to redirect these old URLs to a new URL. Essentially, I just need to have a Wordpress function redirect from /downloads/view.php?id=2 to /downloads/2/, or another more optimized URL (/downloads/title-of-archive).

How would I go about handling pages with a URL of "/downloads/view.php" and "/downloads/download.php" and performing the redirect?

I know I can use the .htaccess file, but I'd prefer to do this directly in a Wordpress plugin if possible for portability...

share|improve this question
    
Is your web server an Apache? If so, I would handle that in the Apache config or .htaccess file. –  toscho Oct 27 '12 at 23:26
    
This seems more like a question for Server Fault, as it deals more with .htaccess then WordPress. –  bungeshea Oct 28 '12 at 0:05
    
I'd prefer to do this in a Wordpress plugin to avoid having to make this modification to servers I move to in the future or after reinstalling Wordpress... –  Andrew M Oct 30 '12 at 23:36
    
@AndrewM I added a solution which actually puts in the URL for you :) –  Derk-Jan Jan 16 '13 at 14:27
add comment

3 Answers

To redirect /downloads/view.php?id={some-name} to /downloads/{some-name}/, add the following to your .htaccess file, before the default WordPress rules

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^downloads/view.php?id=(.+) downloads/$1 [R=301,L]
</IfModule>

It will also let search engines know that your downloads have moved, and to update their index.

share|improve this answer
    
Is there a way to do this directly from Wordpress, without modifying the .htaccess file? –  Andrew M Oct 30 '12 at 23:37
    
There is the Rewrite API, but that's more for making ugly URLs (with query args, such as downloads/view.php?id=2) look pretty (like /downloads/2/), not the other way around. For more info on the Rewrite API, check out the WordPress Codex or this WPSE answer. –  bungeshea Oct 31 '12 at 6:00
add comment
up vote 0 down vote accepted

I ended up solving the issue by hooking onto the "template_redirect" action. After that, I check if the page is_404() and then check if the URL matches my pattern. I set the appropriate header (301 versus the 404 that normally would be triggered) and perform my redirect. My code is below.

add_action('template_redirect', 'handle_download_urls');

function handle_download_urls(){
    if(is_404()){
        if(preg_match('/\/downloads\/(?:view\.php|download\.php)/', $_SERVER['REQUEST_URI']) && isset($_GET['id'])){
            // Do lookup of post based on custom metadata field
            // Redirect and change header
            status_header(301);
            header('Location: [URL]');
       }
    }
}
share|improve this answer
add comment

You could do this with rewrites, but honestly, it's not a rewrite what you want. A rewrite would just have the old url to act like the new url instead of redirecting it to the new location. Please not that you still need to make sure /downloads/id/ is handled by your WordPress. Now there you could use rewrite.

Add the following code to your templates function.php:

if ( !function_exists( 'get_current_url' ) ) {
    /**
     * Gets the current displayed url
     * @returns the url
     */
    function get_current_url( ) {
        $url  = isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ? 'https://' : 'http://';
        $url .= ( strlen( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : $_SERVER['HTTP_HOST'] );
        $url .= ( strval( $_SERVER['SERVER_PORT'] ) != '80' ) ? $_SERVER['SERVER_PORT'] : '';
        $url .= $_SERVER[ 'REQUEST_URI' ];
        return $url;    
    }
}

/**
 * Permanently redirects old /downloads/view.php?id=X and /downloads/download.php?id=X
 * to /downloads/X/. 
 */
function permanent_301_redirect_downloads() {  

    $matches = array();
    $url = get_current_url();

    // $matches[1] has view or download, and $matches[2] the id
    if ( preg_match( '/downloads\/(view|download)\.php\?id=([0-9]+)\/?$/', $url, $matches ) ) :
        // Fetch the title of the archive. Are these posts? I wouldn't know
        $archive = $matches[2];
        wp_redirect( trailingslashit( home_url('') . '/downloads/' . $archive ) , 301 );  
        exit;
    endif;

}  
add_action( 'template_redirect', 'permanent_301_redirect_downloads' );  
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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