Forum Moderators: phranque

Message Too Old, No Replies

MySQL archive / auto links with $ GET id -- .htaccess

         

Readie

6:19 am on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ok, I have a website with several news posts appearing on the index page, and then an archive page with links to all previous news posts.

Each news post is given it's own id in a MySQL database, and the link used to display the information is archiveitem.php?id=1

Now, I want the URL to display as .../archiveitem/1, but my htaccess knowledge is just too undeveloped for me to have any idea how to phrase that as a rewrite rule.

A secondary option is for assistance in declaring $_POST data on link click, however I am not certain how to code that at all, and would prefer not to resort to that method so as to enable visitors to link to the news posts directly.

Any help anyone could offer me would be much appreciated.

Regards,
Readie

jdMorgan

3:33 pm on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



See the thread Changing Dynamic URLs to Static URLs [webmasterworld.com] and the other threads in our Apache Forum Library [webmasterworld.com] for a good start, using the references cited in our Apache Forum Charter [webmasterworld.com], then post specific questions back here. :)

Jim

Readie

6:23 pm on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for that :) wrote

RewriteRule ^archiveitem/([^/]+)/?$ /archiveitem.php?id=$1 [L]

and it works beautifully, although I did have a little trouble with page formatting (as in, there wasn't any :)) until I realised I needed my link tag to point to /sitemain/style.css rather than just sitemain/style.css.

g1smd

11:55 pm on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You also need the same linking format for image and JS files too.

Readie

5:06 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ok, just to build on this, I'm curious if it's possible to have a rewrite for if there is an id declared, as well as if there is not an id declared.

So, the above sends me to archiveitem/id, however writing another rewrite to send me just to archiveitem returns a internal server error, as it's picking up on both scripts and trying to send me to 2 locations.

jdMorgan

5:55 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It doesn't "send" anything anywhere; It changes the filepath to which the HTTP URL-path would normally resolve to a non-default value. There's no way that one HTTP request can result in serving two files just from being rewritten.

The likely problem is that your new rule rewrites the request to a path that matches its own pattern, resulting in an 'infinite' rewriting loop. This should be obvious from the entries in your server error log.

Can't comment further on code I can't see...

Jim

Readie

6:18 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Don't worry, I've got it working :)

<IfModule mod_rewrite.c>

Options +FollowSymLinks
RewriteEngine on

RewriteRule ^archiveitem/([^/]+)/?$ /archiveitem.php?id=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

</IfModule>

I switched the location in the document of the archiveitem and the general rule.

Thanks for the clarification on what a htaccess actually does though, I was curious how it worked but never got around to actually looking it up.

Readie

11:20 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



just incase anyone tries to use this code, I discovered that if a trailing slash is added to any URL on the site (aside from the index) then it causes an infinite loop.

Fixed it by adding this to the general rule above:

RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301] 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

g1smd

11:54 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



While you 'fixed' it, I have a feeling that you have introduced some other non-obvious problems.

The new redirect needs the [L] flag.

The new rule messes with canonicalisation if non-www is requested.

Readie

11:58 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ah yes, oops. Cheers for pointing that out :)

EDIT -----

I'm sorry for my constantly returning to this thread, but this is my first attempt at creating a working .htaccess file.

I'm finding that if someone adds a trailing slash, and then adds a false bit of data on the end, say, example.co.uk/roster/ihgu it's causing an infinite loop.

[error] [client <SNIP>] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

My full .htaccess file is as follows:

<IfModule mod_rewrite.c>

Options +FollowSymLinks
RewriteEngine on

RewriteCond %{HTTP_HOST} !^www\.SNIP\.co\.uk$
RewriteRule (.*) http://www.SNIP.co.uk/$1 [R=301,L]

RewriteRule ^$ /index.php [L]
RewriteRule ^archive/([^/]+)/?$ /archive.php?id=$1 [L]
RewriteRule ^archiveitem/([^/]+)/?$ /archiveitem.php?id=$1 [L]

RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

</IfModule>

ErrorDocument 404 /404.php

Could anyone offer assistance on what needs to be changed in order to cause entering a false URL such as the one above to return a 404?

EDIT 2 -----

Please note this only occurs for files that actually exist, so whilest roster/hiur returns the 500 error, elje/jeoler returns a 404

g1smd

12:28 am on Jan 20, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Rule ordering is important; you have rewrites before redirects. That always causes trouble as internal filepaths can be re-exposed back out into URLs.

In your case, the rewrites still accept a URL with or without a trailing slash. They need to accept only requests without the trailing slash.

The canonicalisation rule needs to be listed before those rewrites and even before the general non-www to www redirect rule.

The first rule also needs to fix the domain as well as the slash within the same rule in order to avoid a redirection chain for some requests.

Readie

1:13 am on Jan 20, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I don't know how to do some of what you said there (but I am looking for a good guide there as I want to learn how to do it myself, not just be given the answer).

However; moving the cannocalization rewrites above the www/non-www, for some reason exposes the file name and extension on the index page (link href="/")(URL http://www.example.co.uk/index.php)

And I made sure that the remove trailing slash was below the index redirect.

g1smd

8:38 am on Jan 20, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If the rules in the post above are labelled 1, 2, 3, 4, then the new order should be 3, 1, 2, 4.

jdMorgan

3:14 am on Jan 21, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd suggest:

Options +FollowSymLinks
RewriteEngine on
#
# Externally redirect to remove trailing slashes from archive and archiveitem URLs
RewriteRule ^archive(item)?/([^/]+)/$ http://www.example.co.uk/archive$1/$2 [R=301,L]
#
# Externally redirect non-canonical hostname requests to canonical hostname
RewriteCond %{HTTP_HOST} !^www\.example\.co\.uk$
RewriteRule ^(.*)$ http://www.example.co.uk/$1 [R=301,L]
#
# Internally rewrite requests for "/" to index.php
# (This could likely be replaced by a "DirectoryIndex /index.php" directive)
RewriteRule ^$ /index.php [L]
#
# Internally rewrite archive and archiveitem requests to archive scripts
RewriteRule ^archive(item)?/([^/]+)$ /archive$1.php?id=$2 [L]
#
# Internally rewrite all requested URLs which do not resolve to an existing directory but
# which do resolve to an existing php script when ".php" is appended, explicitly excluding
# URLs ending in .php and "/" to save unnecessary file- and directory-exists checking
RewriteCond $1 !\.php$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*[^/])$ /$1.php [L]

Note that I removed the <IfModule> container -- It's only necessary if you want this code to fail silently on servers where mod_rewrite is not installed.

Jim