.htaccess RewriteRule backreference order - .htaccess

I have a question about htaccess rewriting rule.
Is it possible to convert this url:
www.site.com/en/test
In something like this:
www.site.com/test.php?language=en
I tried to use this RewriteRule
RewriteRule ^([a-z][a-z])/(.*)$ $1.php?language=$2
But in some online testing tool the result URL was:
www.site.com/en.php?language=test
Thank you in advance.
Mat

The reason for this confusion is that you've reversed the matches. When you use references, the first reference in the match is always $1, the second is $2 and so on.
Here's what you did, looking only at the parentheses:
([a-z][a-z]) = first match, places "en" in $1
(.*) = second match, places "test" in $2
So you simply need to reverse them in your output, like this:
RewriteRule ^([a-z][a-z])/(.*)$ $2.php?language=$1

Related

How to rewrite on htaccess

I need to substitute the character %26 for & and %3D for = in my URL:
http://www.example.com/dir/?sort-by=title%26listing_types%3Dcars
I tried the rewrite below but it does not work
RewriteRule ^dir/?$ ?sort-by=$1&listing-types=$2 [QSA,L]
Any help will be welcome
RewriteRule ^dir/?$ ?sort-by=$1&listing-types=$2 [QSA,L]
Your backreferences $1 and $2 don't actually refer to anything so these will always be empty (resulting in empty URL parameters). However, $n backreferences refer back to the RewriteRule pattern, which does not match against the query string anyway. You would need %n type backreferences that refer back to the last matched CondPattern in a preceding RewriteCond directive.
This also looks like it should ideally be a redirect, rather than an internal rewrite? Otherwise, you run the risk of duplicate content.
http://www.example.com/dir/?sort-by=title%26listing_types%3Dcars
You can do something like the following to match the above URL and replace the appropriate characters:
RewriteCond %{QUERY_STRING} ^(sort-by=.*)%26(listing_types)%3D(.*)
RewriteRule ^(dir/)$ /$1?%1&%2=%3 [R,L]
The above would temporarily (302) redirect /dir/?sort-by=<anything1>%26listing_types%3D<anything2> to /dir/?sort-by=<anything1>&listing_types=<anything2>. Change R to R=301 if this should be permanent, but only once you have confirmed it is working OK.
$1 is a backreference to the captured group in the RewriteRule pattern (ie. "dir/") and %1, %2 and %3 are backreferences to the corresponding captured groups in the preceding CondPattern in order to reconstruct the query string.
If you specifically need this to be an internal rewrite then remove the R flag (and optionally remove the slash prefix on the substitution).
http://www.example.com/dir/?sort-by=title%26listing_types%3Dcars
As mentioned in comments, you could instead handle this entirely in your server-side code. For example, in PHP you could do something like:
<?php
$queryString = urldecode($_SERVER['QUERY_STRING']);
parse_str($queryString,$urlParams);
print_r($urlParams);
?>
Given the above request URL, this will output:
Array
(
[sort-by] => title
[listing_types] => cars
)

Rewrite rule to change the url

I want to rewrite a URL like:
http://domainname.com/all-studio-methods
To:
http://domainname.com/review.php?id=25&cas=all-studio-methods
My .htaccess file currently looks like the following:
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^([^/\.]*)$ review.php?id=$1&cas=$2 [L]
But it is not working properly. What am I doing wrong?
As noted in the comments, you have this rule:
RewriteRule ^([^/\.]*)$ review.php?id=$1&cas=$2 [L]
The $1 and $2 are backreferences that are replaced with matched groupings in your reqular expression, ^([^/\.]*)$ which only has 1 grouping, the entire match. So $2 will always be blank since you don't have another grouping. This also means that $1 will be the entire match (e.g. all-studio-methods) and you're going to get a URI like this:
review.php?id=all-studio-methods&cas=
Which is obvioiusly not what you want. The comments ask where the id=25 comes from. It's not coming from the URI, /all-studio-methods. So in order to rewrite to id=25, it's got to be in the URI somewhere, for example:
http://domainname.com/25-all-studio-methods
Then you'd have a rule like:
RewriteRule ^([0-9]+)-([^/\.]*)$ review.php?id=$1&cas=$2 [L]
If you really don't want the 25- in the URI, you'll need to rewrite the php code in review.php so that it doesn't take an id. It would need to fetch the ID internally from the database given a cas.
Or, you could create a rewrite map in order to map cas to an id. It's going to be pretty much the same thing, you're writting code to do it in either case.

Looking for help with 2-tier clean URL's using .htaccess

I am working on a site which will have two levels the URL reaches
My objective is to have clean URL's like this...
http://domain.com/username/dosomething
My ugly URL's currently look like this...
http://domain.com/index.php?page=username&command=dosomething
My attempt was this
RewriteEngine On
RewriteRule ^([a-zA-Z0-9]+)$ index.php?page=$1&command=$2
RewriteRule ^([a-zA-Z0-9]+)/$1/$2 index.php?page=$1&command=$2
You're not using your backreferences correctly in the first part. Backreferences are parenthesised expressions that will then get filled into $1, $2 et al. in the second part of the rule. e.g.:
RewriteRule ^([^/]+)/([^/]+)$ /index.php?page=$1&command=$2
These parenthesized expressions match one or more non-/ characters and fill them into $1 and $2 respectively.
Your references are just referencing your entire URL so what you are telling it to give you is
index.php?page={entire URL}&command={null}
You need to setup the URL and only use parenthesis around the variables page and command. So
^domain.com/([username]+)/(dosomething)
then rewrite with:
http://domain.com/index.php?page=$1&command=$2
provided that your page and command variables are username and dosomething respectively

Problem with .htaccess and RewriteRule

I have url's like games/xbox/2
2 being the page number I need the url rewritten. This is what I'm using:
RewriteRule games/(.*?)/$ games/consoles.php?console=$1
RewriteRule games/(.+?)/(.+?)/$ games/consoles.php?console=$1&page=$2
The first rule works fine but the second is returning consoles.php as $1 instead of xbox
RewriteRule games/([A-Za-z0-9]+)/?$ games/consoles.php?console=$1
RewriteRule games/([A-Za-z0-9]+)/([0-9]+)/?$ games/consoles.php?console=$1&page=$2
Using (.*?) would match even the / character so xbox/2 is treated as a whole
Try something like:
RewriteRule games/([^/]+)/([^/]+)/?$ games/consoles.php?console=$1&page=$2 [L]
RewriteRule games/([^/]+)/?$ games/consoles.php?console=$1 [L]
I first put your most specific rule first - that way you don't do a general match, then a later more specific match mangles that general rewrite.
I also specified the [L] flag to signify that you want the engine to stop looking for more matches at this point. Re-ordering the rules is redundant in this case because of the [L] flag, but it's a good practice to get into.
I also changed the expressions slightly. Rather than using ([A-Za-z0-9]+) like the previous poster said, I changed it to ([^/]+) because that will match everything but a slash, so you can have weird console or game names. If you want to make it more specific feel free to, but this way provides the most general use-case.

.htaccess rewritecond rewrite case level 2 folder=info

I wanted to set .htaccess to rewrite:
example.com/bla/info/
to
example.com/info/index.php?q=bla
example.com/bla/info/txt/
to
example.com/info/index.php?q=bla&t=txt
I wanted the browser still to display:
example.com/bla/info/txt/
I didn't want rewrite in the level 2 rewrites, like:
example.com/bla/xxx/
or
example.com/ccc/zzz/aaa/
but
example.com/silly/info/
would work as well as
example.com/strange/info/mytxt/
Did this make sense?
Any help?
If you start your pattern with ^ and end it with $, the rule will only apply if the whole string matches.
RewriteRule ^/bla/info/$ /info/index.php?q=bla
RewriteRule ^/bla/info/txt/$ /info/index.php?q=bla&t=txt
If you use do not use the [R] option, the URL shown in the browser will be whatever the user entered.
Are you trying to make this general-purpose? If so, you can use regex-type matching and variable substitution. To make 'bla' match any string up to the next slash (/), use
([^/]+)
in your pattern and reference it with $1 in your substitution.
RewriteRule ^/([^/]+)/info/$ /info/index.php?q=$1
RewriteRule ^/([^/]+)/info/([^/]+)/$ /info/index.php?q=$1&t=$2
I recommend the Apache web pages about mod_rewrite for more information.
[Edit. Fixed the rules to not include the host name in the pattern, as the original poster figured out.]
--
bmb
you got me in the right track.
i ended up with something like this:
RewriteRule ^([^/\.]+)/info/?$ example/info/index.php?q=$1 [L]
thanks a lot

Resources