Casey Dwayne
Casey Dwayne

Reputation: 2169

Apache Mod Rewrite for Pretty URLs isn't working

I'm trying to figure out how to do an apache mod_rewrite to remap $_GET.

What I'm trying to accomplish:

Currently, to get to the page one would have to go to

http://www.domain.com/index.php?URL=pages/the-page.php

I would like this to work in 2 ways:

If someone goes to domain.com/the-page, it takes them to the above but keeps it looking like this. Secondly, if someone goes to the http://www.domain.com/index.php?URL=pages/the-page.php, it will still show as domain.com/the-page, keeping the URL short and clean.

Most Recently Tried Code

Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/index\.php$
RewriteCond %{QUERY_STRING} URL=pages/([a-z0-9-_]+)\.php$
RewriteRule ^(.*) /%1

I'm pretty sure I setup everything right in the apache httpd.conf. I'm using XAMPP to test locally, restarted apache on changes, still nothing. Where am I going wrong?

I would prefer to handle this in .htaccess

I am using XAMPP localhost and trying on live server.

Log File:

127.0.0.1 - - [05/Apr/2013:16:50:43 --0400] [localhost/sid#2f3140][rid#3b14068/initial] (3) [perdir C:/xampp/htdocs/cdi/] strip per-dir prefix: C:/xampp/htdocs/cdi/index.php -> index.php

127.0.0.1 - - [05/Apr/2013:16:50:43 --0400] [localhost/sid#2f3140][rid#3b14068/initial] (3) [perdir C:/xampp/htdocs/cdi/] applying pattern '^(.*)' to uri 'index.php'

127.0.0.1 - - [05/Apr/2013:16:50:43 --0400] [localhost/sid#2f3140][rid#3b14068/initial] (1) [perdir C:/xampp/htdocs/cdi/] pass through C:/xampp/htdocs/cdi/index.php

Updated log with Olaf's script (last rule commented out)

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (3) [perdir C:/xampp/htdocs/cdi/] strip per-dir prefix: C:/xampp/htdocs/cdi/index.php -> index.php

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (3) [perdir C:/xampp/htdocs/cdi/] applying pattern '^' to uri 'index.php'

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (3) [perdir C:/xampp/htdocs/cdi/] strip per-dir prefix: C:/xampp/htdocs/cdi/index.php -> index.php

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (3) [perdir C:/xampp/htdocs/cdi/] applying pattern '^index\.php$' to uri 'index.php'

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (2) [perdir C:/xampp/htdocs/cdi/] rewrite 'index.php' -> '/newhome?'

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (3) split uri=/newhome? -> uri=/newhome, args=<none>

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (2) [perdir C:/xampp/htdocs/cdi/] explicitly forcing redirect with http://localhost/newhome <--this one seems to be causing the issue

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (1) [perdir C:/xampp/htdocs/cdi/] escaping http://localhost/newhome for redirect

127.0.0.1 - - [05/Apr/2013:20:02:24 --0400] [localhost/sid#2e3140][rid#3b14090/initial] (1) [perdir C:/xampp/htdocs/cdi/] redirect to http://localhost/newhome [REDIRECT/302]

Thank you everyone that is helping. I've spent 2 days trying to get this to work!!!

Upvotes: 2

Views: 1926

Answers (4)

Olaf Dietsche
Olaf Dietsche

Reputation: 74028

Basically, you need two rules. One rule to redirect the client to a clean URL and another to internally rewrite the pretty URL to the real content via index.php.

Assuming the index.php and .htaccess is in a directory cdi

RewriteEngine on

# prevent endless loop
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

# redirect the client
RewriteCond %{QUERY_STRING} URL=pages/(.+?)\.php
RewriteRule ^index\.php$ /cdi/%1? [R,L]

# exclude rewriting all files located in /cdi/files
RewriteCond %{REQUEST_URI} !^/cdi/files/
# rewrite to real content
RewriteRule ^.*$ /cdi/index.php?URL=pages/$0.php [L]

Update:

When the request is /cdi/index.php?URL=pages/abc.php, the second rule extracts the needed URL part and redirects the client to the new URL path. The client then requests the new URL /cdi/abc and the third rule takes this and does an internal rewrite to the real content.

This all works fine as it should, but would rewrite and redirect indefinitely. To break this endless rule, the first rule checks the environment %{ENV:...}, if the request was already redirected REDIRECT_STATUS and then stops the cycle with the RewriteRule

RewriteRule ^ - [L]

which matches everything ^ and does no substitution, but ends the rewrite cycle with the flag [L]

Instead of using the system provided environment STATUS/REDIRECT_STATUS, you can also set a variable yourself with the flag E=SEO:1 for example, and then test for this variable with

RewriteCond %{ENV:REDIRECT_SEO} 1

For the REDIRECT_ prefix, see Available Variables.

Upvotes: 2

If you want the group ([0-9]+) to be alphabetic then just change it to ([a-z]+) and if you've wanted it to be alphanumeric, then change it to ([a-z0-9]+), and ([a-z0-9-_]+) if with a hyphen and an underscore. If you've wanted it to set their limits manually, you can do that with this format ([a-z0-9-_]{1,40}). Do you see, the plus sign is gone, for it limited the [chars] with 1 to anything, and the {1,40} limited the [chars] with 1 to 40, you can either change it.


Do you know what the real problem is? Is my stress.. Imagine even I know that you want to remap /$var into /index.php?URL=pages/$var.php I'm still trying giving you a wrong information that will rewrite /index.php?URL=pages/$var.php into /$var. I just have realize that after my 4 hours sleep. Did you see what's happening when the time of your sleep isn't right? Maybe a rule I would gives to you when my brain's in functioning well, was:

RewriteRule ^([a-z0-9-_]+)/?$ /index.php?URL=pages/$1.php

Why did the viewers letting this to happened.. My previous codes are needed to be voted down.

Upvotes: 0

awendt
awendt

Reputation: 13663

You approach seems fine but your RewriteCond doesn't match your requirements:

RewriteCond %{REQUEST_URI} ^index.php?URL=pages

means "rewrite the URL if someone requests something that starts with 'index.php"—but that's not what anyone will be requesting. You want your visitors to request pretty URLs.

If your server only needs to serve those requests for /the-page, you can drop the condition entirely. Then any URL will be rewritten. (Note: This might not be what you want!)

Otherwise, the condition should read something like this:

RewriteCond %{REQUEST_URI} ^[a-z0-9-_]{1,40}

If you don't want to mess with regular expressions, you could also try this:

RewriteCond %{REQUEST_FILENAME} !-f  

which means "if the user requests a URL for which no file can be found, rewrite the URL according to the upcoming RewriteRule."

Upvotes: 0

Bobulous
Bobulous

Reputation: 13169

You could try this:

RewriteRule ^/([a-z0-9_-]{1,40})/?$ index.php?URL=pages/$1.php

Though ideally you might want to get rid of the "pages/" part of the query string variable, as this fixed constant could be handled by the index.php script.

Upvotes: 0

Related Questions