Forum Moderators: phranque

Message Too Old, No Replies

Tricky URL Rewrite

at least for me

         

JeremyL

12:02 am on Jul 18, 2005 (gmt 0)

10+ Year Member



Right now I have a very simple rewite


Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule (.*)/(.*)/(.*)/$ /main.php?state=$1&city=$2&listing=$3
RewriteRule (.*)/(.*)/$ /main.php?state=$1&city=$2
RewriteRule (.*)/$ /main.php?state=$1

So basically I can have the following urls
domain.com/texas/
domain.com/texas/dallas/
domain.com/texas/dallas/listing/

But I need to be able to also show brands at a state and/or city level along with the others. Something like this
domain.com/texas/brand1/
domain.com/texas/brand2/
domain.com/texas/dallas/brand1/
domain.com/texas/dallas/brand2/

Is this even possible without messing up the original rewrites? Would I need to add a new delimiter to show a difference between the two? I am at the design stage so I can design it however.

jd01

12:36 am on Jul 18, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I think this is a case where I would use a delimiter (I will call it products, but you can use any thing shorter and more efficient that is unique to defining a product) and skips...

1st I would change this:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule (.*)/(.*)/(.*)/$ /main.php?state=$1&city=$2&listing=$3
RewriteRule (.*)/(.*)/$ /main.php?state=$1&city=$2
RewriteRule (.*)/$ /main.php?state=$1

to:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /main.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ([^/]+)/([^/]+)/$ /main.php?state=$1&city=$2 [L]
RewriteRule ([^/]+)/$ /main.php?state=$1 [L]

Always use the [L] last flag unless you know you do not need it.
[^/]+ = 1 or more of anything that is not a /, slightly more efficient, because there is no need to 'back-track' for any reason EG break the match at the /

2nd I would change the /main directory to /1main for efficiency - you should see why in a minute:

RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2&listing=$3
RewriteRule ([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2
RewriteRule ([^/]+)/$ /1main.php?state=$1

3rd I would add my skips:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /

# if the URL has already been rewritten, skip the rewrite rules, we know there is no additional rewrite necessary if the URL starts with a 1.
RewriteRule ^1 - [S=7]

# if the URL does not contain the word product, skip the next 3 rules to the other rewrite section. This allows us to only need to match the a word once, and if we do, let the 'catch-alls' act on it:
RewriteRule!product - [S=3]
RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /1product.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ([^/]+)/([^/]+)/$ /1product.php?state=$1&city=$2 [L]
RewriteRule ([^/]+)/$ /1product.php?state=$1 [L]

RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2 [L]
RewriteRule ([^/]+)/$ /1main.php?state=$1 [L]

The ordering of these will have an impact on efficiency, so you will want to stucture the most used URL's to match the 1st set, this could be done by reversing the order of the catch-all rules and changing the skip line to:
RewriteRule product - [S=3]

Hope this helps.

Justin

Edited: missed a - in the skip rule

JeremyL

2:43 am on Jul 18, 2005 (gmt 0)

10+ Year Member



I changed it up just a bit so I could extract the brand and also have it work if no trailing slash was put at the end of the url. Thanks for the help.

Options +FollowSymLinks
RewriteEngine on
RewriteBase /

RewriteRule ^1 - [S=10]

RewriteRule all - [S=6]
RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ([^/]+)/([^/]+)/([^/]+)$ /1main.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2 [L]
RewriteRule ([^/]+)/([^/]+)$ /1main.php?state=$1&city=$2 [L]
RewriteRule ([^/]+)/$ /1main.php?state=$1 [L]
RewriteRule ([^/]+)$ /1main.php?state=$1 [L]

RewriteRule ([^/]+)/([^/]+)/([^/]+)-all/$ /1product.php?state=$1&city=$2&make=$3 [L]
RewriteRule ([^/]+)/([^/]+)/([^/]+)-all$ /1product.php?state=$1&city=$2&make=$3 [L]
RewriteRule ([^/]+)/([^/]+)-all/$ /1product.php?state=$1&make=$2 [L]
RewriteRule ([^/]+)/([^/]+)-all$ /1product.php?state=$1&make=$2 [L]

jdMorgan

3:35 am on Jul 18, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No need to have two rules just because of trailing slashes. For example, change:

RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ([^/]+)/([^/]+)/([^/]+)$ /1main.php?state=$1&city=$2&listing=$3 [L]

to:

RewriteRule ([^/]+)/([^/]+)/([^/]+)[b]/?$[/b] /1main.php?state=$1&city=$2&listing=$3 [L]

This will handle either case, trailing slash or no trailing slash.

Jim

JeremyL

4:21 am on Jul 18, 2005 (gmt 0)

10+ Year Member



I was actually thinking about the trailing slash. If a SE sees both /texas and /texas/ with the same content, it may see one as a dir and one as a file and see them as dupe content. With that in mind I set out to redirect the one without the trailing / to the one with the trailing /. But I am having one small problem.

#start

Options +FollowSymLinks
RewriteEngine on
RewriteBase /

RewriteRule ^1 - [S=10]

RewriteRule all - [S=6]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ $1/$2/$3/ [R]
RewriteRule ([^/]+)/([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2&listing=$3 [L]
RewriteRule ^([^/]+)/([^/]+)$ $1/$2/ [R]
RewriteRule ([^/]+)/([^/]+)/$ /1main.php?state=$1&city=$2 [L]
RewriteRule /^([^/]+)$ $1/ [R]
RewriteRule ([^/]+)/$ /1main.php?state=$1 [L]

RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ $1/$2/$3/ [R]
RewriteRule ([^/]+)/([^/]+)/([^/]+)-all/$ /1product.php?state=$1&city=$2&make=$3 [L]
RewriteRule ^([^/]+)/([^/]+)$ $1/$2/ [R]
RewriteRule ([^/]+)/([^/]+)-all/$ /1product.php?state=$1&make=$2 [L]

#end

Everything seems to be working but the one line
RewriteRule /^([^/]+)$ $1/ [R]

domain.com/first-var is the only one that doesn't add the / at the end. domain.com/first-var/second-var and also with the third var redirects fine.

domain.com/first-var just shows a 404 error. I tried removing the first "/" in the "RewriteRule /^([^/]+)$ $1/ [R]" but that causes issues with the whole domain. Any ideas how to get the first var working?

jd01

4:27 am on Jul 18, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Probably better to address this outside of the rulesets. This is from a previous thread:

# If path does not end in "/"
rewriteCond %{REQUEST_URI} !/$
# and does not contain a "."
rewriteCond %{REQUEST_URI} !\.
# then add trailing slash and redirect
rewriteRule ^(.*) /$1/ [R=301,L]

Justin

jdMorgan

4:13 pm on Jul 18, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There are three problems with this:

RewriteRule /^([^/]+)$ $1/ [R]

  • The pattern "/^" is either reversed or incorrect. "^" is a pattern-match start anchor, and should be first.
  • You have specified a 302 (temporarily-moved) redirect, which is not what you want. Use [R=301].
  • If using any [R] flag, specify a canonical URL, such as

    RewriteRule ^/([^/]+)$ http://www.example.com/$1/ [R=301]

    Also, unless further rules need to be processed for this HTTP request after the rule is invoked, use the [L] flag as well, e.g. [R=301,L]. It is far more coomon to use the [L] with [R] than it is to omit it; See the mod_rewrite documentation of RewriteRule flags.

    Jim

  •