views:

36

answers:

1

I'm about to update my site to use CakePHP instead of an old homegrown framework. I need to write the HTAccess file to redirect the old PHP parameter URLs to the new CakePHP SEO friendly urls, but I can't get it to work.

My htacess file (the one in app/webroot) looks like this at the moment:

RewriteEngine On

RewriteRule ^index.php?action=view&item=172$ index.php?url=item/172 [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

It doesn't work. I tried removing the L and just having it redirect to item/172, but that didn't work either. The current one winds up with the URL parameter unset, and if I look in $_SERVER['REQUEST_URI'] it is unchanged. Though I don't know if mod_rewrite would change that. My rewrite rule doesn't seem to be activating, even though that is directly copied from the URL bar of my browser. I tried it with out and with out a leading /. No dice.

What's going on here?

And how can I write a more generalize URL to do the conversion? I tried something like:

RewriteRule ^index.php?action=view&item=([0-9]+)$ index.php?url=items/$1 [R=301,L]    

But that didn't work either. What am I doing wrong?

EDIT This is positively infuriating.

RewriteRule ^(.*)$ /index.php?url=item/172 [R=301]

That works. It funnels ALL urls into that correctly formed Cake url. Which cake's processor then picks up and somehow handles. I'm not sure how it misses Cake's second rewrite rule, but it does. Trying this:

RewriteRule ^(.*)$ item/172 [R=301]

Returns a malformed redirect, as does specifying last on the previous one:

RewriteRule ^(.*)$ /index.php?url=item/172 [R=301,L]

That declares that it could never complete.

So I'm actually rather baffled as to why this one:

RewriteRule ^(.*)$ /index.php?url=item/172 [R=301]

Returns the correct Cake url, but it does and it gets sent to the correct page. However, as soon as I attempt to change the first part, it starts failing.

Wait a second. It's when it hits the ? that it starts failing. It successfully matches index.php but not index.php? But escaping it makes no difference.

RewriteRule ^index.php\?$ /index.php?url=item/172 [R=301]

That fails to match or return the correct URL. And it doesn't seem to match Cake's normal catch all either, because $_GET['url'] is empty. How do you escape parameter characters to match literally in mod_rewrite?

+2  A: 

With RewriteRule you can only test the URI path but not the query:

The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string. If you wish to match against the hostname, port, or query string, use a RewriteCond with the %{HTTP_HOST}, %{SERVER_PORT}, or %{QUERY_STRING} variables respectively.

So:

RewriteCond %{QUERY_STRING} ^action=view&item=([0-9]+)$
RewriteRule ^index\.php$ /index.php?url=item/%1 [R=301,L]
Gumbo
Thank you! That did it. Somehow, in all of my reading and searching this never got mentioned or came up. And it never occurred to me that the query string would be separated from the primary URL.
Daniel Bingham