.htaccess for friendly URL with multiple variables
Using just:
RewriteEngine On
Options -Indexes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?page=$1 [L,QSA]
is fine then you can route the request within your script.
You split the page variable with explode() delimiter / and then set the variables.
$route = explode('/',$_GET['page']);
$page = isset($route[0]) ? $route[0] : null;
$subpage = isset($route[1]) ? $route[1] : null;
$yada = isset($route[2]) ? $route[2] : null;
Many MVC frameworks use this method. Its called routing.
htaccess - pretty url with multiple variables
With your shown samples, please try following. This considers that you want to hit URL like: http://localhost:80/sky.php?c=something&id=9&s=anything
in browser which should be redirected to http://localhost:80/something/9/anything
here.
Please make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##This rule handles to change from non-friendly URL to friendly URL in browser.
RewriteCond %{THE_REQUEST} \s/(?:[^.]*)\.php\?c=([^&]*)&id=([^&]*)&s=([^\s&]*) [NC]
RewriteRule ^ /%1/%2/%3? [R=301,L]
##This rule internally rewrites friendly url to non-friendly url.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/?$ sky.php?c=$1&id=$2&s=$3 [L]
Friendly URL for multiple and long queries
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:
<IfModule mod_rewrite.c>
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]
</IfModule>
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)
URL rewrite with .htaccess for multiple-language site (multiple variables)
That's not possible the way you're trying to do it since apache doesn't know when it's a language value (like no
or eng
) or when it's a page (like about-us
.)
Let me explain you how I would do this:
RewriteRule ^([^/]+)/?$ /index.php?g1=$1 [L,QSA]
so now if I'd go to example.com/about-us/
then this will be the same as example.com/index.php?g1=about-us
or the other (your language url) would be example.com/index.php?g1=no
.
now in PHP you need to check it like this:
if($_GET['g1'] == "no")
//Norwegian language
else if($_GET['g1'] == "about-us")
//About us page
else
//Page doesn't exist
.htaccess multiple parameters in URL
You can't do this "indefinitely" using .htaccess
alone. You would need to decide on the maximum number (N) of parameters and write a directive for each in order: N, N-1, N-2, ... 1. However, you are also limited by the number of backreferences that are supported. ie. With just $1
to $9
, you are limited to 4 parameters, using your method of including the parameter name in the URL path as well.
For example:
# 3 additional parameters
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/?$ index.php?page=$1&$2=$3&$4=$5&$6=$7 [L]
# 2 additional parameters
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/?$ index.php?page=$1&$2=$3&$4=$5 [L]
# 1 additional parameter
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/?$ index.php?page=$1&$2=$3 [L]
# No parameters (just the page)
RewriteRule ^([\w-]+)/?$ index.php?page=$1 [L]
These all allow an optional trailing slash (as in your current example). However, you are better off deciding whether a trailing slash is required or not and choosing one or the other. Having the trailing slash optional simply promotes duplicate content.
This URL pattern is also a bit too "generalised" in my opinion. It is more usual to be specific and avoid including the parameter name in the URL. For example: example.com/home/value1/value2/value2
- the parameter names (param1
, param2
, etc.) would be hardcoded in the RewriteRule
substitution. This would also allow you to have twice as many parameters.
RewriteRule ^([\w-]+)?$ index.php?page=$1 [L]
RewriteRule ^([\w-]+)/?$ index.php?page=$1 [L]
You shouldn't need two directives here. (Providing the DirectoryIndex
is set correctly.)
Rewriting URLs with htaccess, multiple parameters
Please don't create OR test rules on online sites, they are NOT trust worthy, so kindly test these rules into your localhost OR apache.
With your shown samples/attempts, please try following htaccess rules. Considering that you are hitting URL https://mywebsite.com/pages/article.html?id=1&title=Title-Goes-Here
in browser AND you want to redirect it to URL https://mywebsite.com/pages/article/1/Title-Goes-Here
in browser.
Please make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##External redirect in browser rules here....
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{THE_REQUEST} \s/([^/]*)/([^.]*)\.html\?id=([^&]*)&title=(\S+)\s [NC]
RewriteRule ^ /%1/%2/%3/%4? [R=301,L]
##Internal rewrite to html file rules here....
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/([^/]*)/?$ $1/$2.html?id=$3&title=$4 [QSA,NC,L]
HTACCESS: Dynamic rewrite url with multiple variables
I'm not an expert but I think this will do it for you:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^/]+)/([^/]+) index.php?p=$1&article=$2 [L]
Where [^/]+
matches everything except /
, result when tested on htaccess.madewithlove.be
EDIT:
as I totally forgot that the second parameter is optional, the great update in the OP almost did it except the fact that it adds a /
at the start of parameter2 value, because $2
is capturing the outer group, while we need the inner one, as shown in this image:
Instead replace $2
with $3
and this should fix it:
RewriteRule ^([^/]+)(/([^/]+))? ?p=$1&article=$3 [L]
Related Topics
Calling a Controller Function in Another Controller in Codeigniter
Can Mongodb and Its Drivers Preserve the Ordering of Document Elements
Set Multiple='False' in a Form in a Many to Many Relation Symfony2
Pdo SQL-State "00000" But Still Error
PHP $String{0} VS. $String[0];
Check If Username Exists in MySQL Table via PHP
How to Read the Query String in PHP and HTML
Adding User Custom Field Value to Order Items Details
Check If Method Exists in the Same Class
How to Check If the Request Came from Mobile or Computer in PHP
PHP Upload Image to Remote Server with Curl
I Want Get the Sum of Files Size in Folder by PHP
Unable to Scrape Content from a Website
How to Implement a Read-Only Member Variable in PHP
Running Job in the Background from Perl Without Waiting for Return
How to Start Local Server with Symfony 5 or Downgrade Version to 4.4