Wednesday, 11 May 2016

apache - Friendly URL for multiple and long queries



I tried a few different questions:




  1. php - .htaccess make URL user friendly for multiple and dynamic parameters

  2. .htaccess for friendly URL with multiple variables

  3. User-friendly URLs instead of Query Strings?




The questions above were not useful, so I began to develop an alternative, but my code is returning an 404 error with multiple requests(code1), and with one request worked well(code2) So:



(code1) - Don´t Work - Multiple Resquest
(code2) - Work Fine - Single Request



Code1






Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)$ /~loja/index.php?a=$1&genero=$2&material=$3&cor=$4&tamanho=$5&Ordenacao=$6 [NC,L,QSA]
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ /~loja/$1/$2/$3/$4/$5/$6 [R=301,L]
DirectoryIndex index.php




Now see the Correct Code:



Code2





Options +FollowSymLinks -MultiViews
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)$ /~loja/index.php?a=$1 [NC,L,QSA]
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ /~loja/$1 [R=301,L]
DirectoryIndex index.php



What is wrong with (code1)?



Answer



The first ruleset is not working because the goal URL contains 7 segments, but the RewriteRule matches 6 segments. If you add another /([^/]*) before the $ in the RewriteRule, it'll work.



So, it'd be:





RewriteRule ^([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)$ /~loja/index.php?a=$1&genero=$2&material=$3&cor=$4&tamanho=$5&Ordenacao=$6 [NC,L,QSA]



You may make a segment/character optional by appending a ? character at the end of it.



The second part of the first ruleset is completely wrong and serves no purpose. First, you should note that THE_REQUEST variable contains the full HTTP request line as the documentation states:




THE_REQUEST contains the full HTTP request line sent by the browser to the server (e.g., GET /index.html HTTP/1.1). This does not include any additional headers sent by the browser. This value has not been unescaped (decoded), unlike most other variables below.




You don't want to use that, use REQUEST_URI instead.




The 404



The reason you're getting that 404 error, is that because the RewriteRule fails to match the request URI, the URL does not get rewritten to index.php. That directory hierarchy does not exist on the filesystem, thus the 404.



Optional URI segments



Your original ruleset was expecting exact count of URI arguments. If you need to be more flexible about this, you can try this ruleset which accepts 1-7 segments and map them to query strings:




RewriteEngine on


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^([^/]*)/?([^/]*)/?([^/]*)/?([^/]*)/?([^/]*)/?([^/]*)/?([^/]*)$ /~loja/index.php?a=$1&genero=$2&material=$3&cor=$4&tamanho=$5&Ordenacao=$6 [NC,L,QSA]



When you test this, note the empty query strings. On the PHP side of things, you need to use empty() instead of isset(), to see if the querystring exists. As they're always set, but empty.




Excluding admin/



In order to exclude this rules to be applied on the admin/ path, you can update the above RewriteCond like this:



RewriteCond %{REQUEST_URI} !(index\.php|admin)

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...