Search code examples
.htaccessurlampersand

Ampersands in URL problems


I have a php page which creates URL like:

vendors/London City/cat-DJ & Entertainment/keywords

which my .htaccess redirects as shown below

RewriteRule vendors/(.+)/cat-(.+)/(.+)$ vendors.php?location=$1&category=$2&freetext=$3 [L]
RewriteRule vendors/(.+)/cat-(.+)/(.+)/$ vendors.php?location=$1&category=$2&freetext=$3 [L]

problem 1 is : in the vendors.php file, I am getting only "DJ ; Entertainment" as category. The ampersand is missing.

Problem 2 is : My complete .htaccess file is shown below... 6 rules are defined.

RewriteRule vendors/(.+)/(.+)/$ vendors.php?location=$1&freetext=$2 [L] 
RewriteRule vendors/(.+)/(.+)$  vendors.php?location=$1&freetext=$2 [L]
RewriteRule vendors/(.+)/cat-(.+)/$ vendors.php?location=$1&category=$2 [L]
RewriteRule vendors/(.+)/cat-(.+)$  vendors.php?location=$1&category=$2 [L]
RewriteRule vendors/(.+)/cat-(.+)/(.+)$ vendors.php?location=$1&category=$2&freetext=$3[L]
RewriteRule vendors/(.+)/cat-(.+)/(.+)/$ vendors.php?location=$1&category=$2&freetext=$3[L]

Why the URL vendors/London City/cat-DJ & Entertainment/keywords is matching with rule 3 or 4 and redirecting to vendors.php?location=$1&category=$2 ?

Does .htaccess Process the rules from top to beginning one by one?

I had solved the problem by putting the rules 5 and 6 at the top of other rules. Did I make the correct fix?


Solution

  • 1. I don't really like the idea of having spaces and other special characters in the URLs. I don't know if it's possible with your site, but instead of this kind of URL

    vendors/London City/cat-DJ & Entertainment/keywords
    

    you should have this one:

    vendors/london-city/cat-dj-and-entertainment/keywords
    

    For that, of course, you will have to perform some additional transformations / lookups in your database to convert london-city back to London City and dj-and-entertainment back to DJ & Entertainment. This can be done by storing these "from-to" pairs in database.

    2. In any case -- order of rules matters. Therefore you should start with more specific rules and end up with more generic rules.

    Also -- the (.+) pattern is a way too broad as it can match hello as well as hello/pink/kitten. To ensure that you always grab only one section (part of URL between /) use ([^/]+) pattern instead -- this will address one of the aspects of your "prob #2".

    Therefore, try these optimized rules (each rule will match the URL with and without trailing slash):

    RewriteRule ^vendors/([^/]+)/cat-([^/]+)/([^/]+)/?$ vendors.php?location=$1&category=$2&freetext=$3 [L]
    RewriteRule ^vendors/([^/]+)/cat-([^/]+)/?$ vendors.php?location=$1&category=$2 [L]
    RewriteRule ^vendors/([^/]+)/([^/]+)/?$ vendors.php?location=$1&freetext=$2 [L] 
    

    Also I'm not getting the value of 'category' with the Ampersand as given in the url. I am getting only semi-colon. What can be the reason?

    I do not have Apache box currently running next to me, so cannot check it right now, but try adding B or NE flag next to the L flag (e.g. [L,B]) -- one of them should help: