I am designing my application. And I should make the next things. All GET parameters (?var=value) with help of mod_rewrite should be transform to the /var/value. How can I do this? I have only 1 .php file (index.php), because I am usign the FrontController pattern. Can you help me with this mod_rewrite rules?Sorry for my english. Thank you in advance.
I do something like this on sites that use 'seo-friendly' URLs.
In .htaccess:
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /index.php [L]
Then on index.php:
if ($_SERVER['REQUEST_URI']=="/home") {
include ("home.php");
}
The .htaccess rule tells it to load index.php if the file or directory asked for was not found. Then you just parse the request URI to decide what index.php should do.
The following code in your .htaccess will rewrite your URL from eg. /api?other=parameters&added=true to /?api=true&other=parameters&added=true
RewriteRule ^api/ /index.php?api=true&%{QUERY_STRING} [L]
.htaccess
RewriteEngine On
# generic: ?var=value
# you can retrieve /something by looking at $_GET['something']
RewriteRule ^(.+)$ /?var=$1
# but depending on your current links, you might
# need to map everything out. Examples:
# /users/1
# to: ?p=users&userId=1
RewriteRule ^users/([0-9]+)$ /?p=users&userId=$1
# /articles/123/asc
# to: ?p=articles&show=123&sort=asc
RewriteRule ^articles/([0-9]+)/(asc|desc)$ /?p=articles&show=$1&sort=$2
# you can add /? at the end to make a trailing slash work as well:
# /something or /something/
# to: ?var=something
RewriteRule ^(.+)/?$ /?var=$1
The first part is the URL that is received. The second part the rewritten URL which you can read out using $_GET. Everything between ( and ) is seen as a variable. The first will be $1, the second $2. That way you can determine exactly where the variables should go in the rewritten URL, and thereby know how to retrieve them.
You can keep it very general and allow "everything" by using (.+). This simply means: one or more (the +) of any character (the .). Or be more specific and e.g. only allow digits: [0-9]+ (one or more characters in the range 0 through 9). You can find a lot more information on regular expressions on http://www.regular-expressions.info/. And this is a good site to test them: http://gskinner.com/RegExr/.
AFAIK mod_rewrite doesn't deal with parameters after the question mark — regexp end-of-line for rewrite rules matches the end of path before the '?'. So, you're pretty much limited to passing the parameters through, or dropping them altogether upon rewriting.
Related
I am trying to change:
example.com/profile.php?id=abcdefgh
To simply:
example.com/abcdefgh
I searched here on StackOverflow and I understood that I need to do something with my .htaccess, I tried this code:
RewriteEngine On
RewriteRule ^([^/]*)$ /profile.php?id=$1 [L]
But it seems nothing changes, when type this URL (example.com/profile.php?id=abcdefgh) it doesn't get rewritten.
P.S. I don't know if the above code is right, i tried it because where I got it from had a similar problem to mine.
This should work.
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ profile.php?id=$1 [QSA,L]
You should be requesting the "pretty" URL, ie. /abcdefgh. Your mod_rewrite directive in .htaccess then internally rewrites this to the "real" URL that actually handles the request (ie. /profile.php?id=$1). That directive is expecting a URL of the form /abcdefgh. However, in its current state I should expect a rewrite loop:
Request /abcdefgh
Request is rewritten to /profile.php?id=abcdefgh.
Processing starts over...
Request is rewritten to /profile.php?id=profile.php (because the regex ^([^/]*)$ matches the profile.php part of the rewritten URL.
GOTO #3
In this example you can avoid the rewrite loop by simply making the RewriteRule pattern (regex) more restrictive. eg. Include a dot (.) in the negated character class (assuming your new "pretty" URLs do not contain a dot).
For example:
RewriteRule ^([^/.]+)$ /profile.php?id=$1 [L]
You then need to actually change the URLs on your website to the new "pretty" URLs.
However, if you are currently getting a 404 then maybe this directive isn't being processed at all? Are .htaccess files enabled? Do you have other directives in your .htaccess file?
UPDATE: in the id the only characters allowed are A-Z
In that case you should be more specific with the regex and match just the characters required. This helps to avoid conflicts and avoids the need for filesystem checks (to some extent) - which are relatively "expensive". Note, however, that you've stated "A-Z" but your example includes lowercase letters. For the sake of argument I'll assume the id can include a-z and A-Z.
So, this now becomes:
RewriteRule ^([a-z]+)$ /profile.php?id=$1 [NC,L]
No other filesystem checks (preceding RewriteCond directives) are necessary. The NC (nocase) makes the regex match case-insensitive.
There is no need to check that the request does not map to a file (with a preceding condition), since the regex ^([a-z]+)$ could never match a file (that includes a file extension).
There is also no need to check that the request does not map to a directory, unless you are requesting directories in the document root directly - which is probably "unlikely". However, therein lies an inherent conflict with this URL structure. If you needed to be able to access a directory then those directory names become invalid IDs - so you would need other checks elsewhere in your system to ensure no IDs were generated that map to physical directories in the document root.
I need to rewrite this url:
mysyte.com/index.php?lang=it
to:
mysite.com/it/index
without rewriting css href, javascript src and image src.
I tried many solutions but none worked, could someone help me?
thanks!
edit:
I tried:
RewriteEngine On
RewriteRule ^(.*)/(.*) $2.php?lang=$1
but this overwrites my css calls too.
then I tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/(.*) $2.php?lang=$1
with the same result
EDIT :
In your .htaccess, write the following lines :
# Activate url rewriting
RewriteEngine on
# Rewrite all url of the form /2-letters-language-code/index to index.php/lang=2-letters-language-code
RewriteRule ^([a-z]{2})/index$ /index.php?lang=$1 [QSA,L]
The ([a-z]{2}) part of the regexp means "every group of two letters", so it will catch "it", but also "fr", "en"... and every other language code in two letters. If this is too general, you can replace it with just (it|en|fr) according to your needs.
And if you need to rewrite not just index to index.php, but whatever alphanumeric string, you can do :
RewriteRule ^([a-z]{2})/([a-zA-Z0-9_]+)$ /$2.php?lang=$1 [QSA,L]
Attention to not be too large in the second parenthesis, otherwise the rule will catch strings you don't want. For exemple,[a-zA-Z0-9_]+ means : every group of 1 or more alphanumeric character and underscores. It excludes slashes (/) and hyphens (-).
This was already answered here :
CSS not loading after redirect with htaccess rewrite rule
the easiest way to fix this is to specify the full path to your CSS file in the <head> of the HTML file.
If your mod_rewrite rule is modifying the path to where your CSS file is, you'd also want to place this before your RewriteRule:
RewriteCond %{REQUEST_FILENAME} !-f
This makes sure that the request doesn't match a file before rewriting it.
I have a very simple url rewriting rules:
RewriteEngine on
RewriteCond %{HTTP_HOST} !script.php
RewriteRule ^test/(.*) script.php?q=$1
The idea is to have this kind of urls: http://mywebsite.com/test/http://example.com
and then send http://example.com to the script.php as a query parameter. The problem is that I'm receiving http:/example.com instead of http://example.com. Also, http:////example.com would be sent as http:/example.com. What causes this behavior ?
Apache mod_rewrite engine converts multiple ///... into single / for pattern matching in RewriteRule directive. However if you match it using RewriteCond then you can match multiple /s.
You can use rule like this:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/+test/+(https?://.+)$ [NC]
RewriteRule ^ script.php?q=%1 [L,QSA]
The browser causes this behaviour. It contracts a sequence of / into 1 /, because it is still essentially a path. ///// does not change the directory we are in, so we could as well use /.
You have two options:
Change your links to use a query string instead. If you rewrite test/?q=something to script.php?q=something everything works as expected. You would do the following:
RewriteRule ^test/?$ script.php [L]
Since you don't alter the query string, the original query string is automatically copied to the new query string.
Don't make an assumption on how many slashes you will encounter. The url might not look correctly in the url bar of the browser, but if it is just a redirect, it will only be visible for a very short period of time.
RewriteRule ^test/(http|https):/+(.*)$ script.php?q=$1://$2
I know how to make URL's rewrite, for example:
www.example.com/index.php?id=1&cat=3 to www.example.com/1/3/ (or whatever). I know that.
What I don't know is how on earth to change my whole links in all pages to link to pretty URL's. All my site's links are old fashion (<a href="index.php?id=1&cat=2">) and there are many.
I`m asking if someone has an idea or know how to automaticaly redirect to that pretty url if the user click on index.php?id=1. (Almost like this site Stackoverflow if you change title in the url).
So my presumtions are...
Use .htaccess to read the index.php?id=1&cat=2 to rewrite index/1/3 that itself interprets again (strange)
a php file to do the redirects that htaccess rewrites back to original...
Conclusion: change <a href="index.php?id=1&....."> automaticaly to index/1/2
SOLVED
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
##################################
# This turns index.php?id=1&cat=2 into index/1/2 and then back 'transparent' into index.php?id=1&cat=2 if you have old fashioned
# links in your site and don't want to change them :)
# Avoid mod_rewrite infinite loops
# This is critical if you want to use this code
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
# Hard-rewrite ("[R]") to "friendly" URL.
# Needs RewriteCond to match original querystring.
# Uses "?" in target to remove original querystring,
# and "%n" backrefs to move its components.
# Target must be a full path as it's a hard-rewrite.
RewriteCond %{QUERY_STRING} ^id=(\d+)&cat=(\d+)$
RewriteRule ^index.php$ http://localhost/index/%1/%2/? [L,R]
# Soft-rewrite from "friendly" URL to "real" URL.
# Transparent to browser.
# Won't re-trigger the above rewrite, though I'm
# not really sure why! The order of the rules
# doesn't seem to make a difference.
RewriteRule ^index/(\d+)/(\d+)/$ index.php?id=$1&cat=$2 [L]
RewriteEngine on
# Prevents browser looping, which does seem
# to occur in some specific scenarios. Can't
# explain the mechanics of this problem in
# detail, but there we go.
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
# Hard-rewrite ("[R]") to "friendly" URL.
# Needs RewriteCond to match original querystring.
# Uses "?" in target to remove original querystring,
# and "%n" backrefs to move its components.
# Target must be a full path as it's a hard-rewrite.
RewriteCond %{QUERY_STRING} ^id=(\d+)&cat=(\d+)$
RewriteRule ^index\.php$ http://example.com/index/%1/%2/? [L,R]
# Soft-rewrite from "friendly" URL to "real" URL.
# Transparent to browser.
RewriteRule ^index/(\d+)/(\d+)/$ /index.php?id=$1&cat=$2
Of course, ideally, you'd just fix your links, and then you'd only require the soft-rewrite. :)
Tested with Apache/2.2.3. I think I made up the terms "hard-rewrite" and "soft-rewrite".
Why not just change your index.php file to do it? You could theoretically do a little more error checking that way, allowing for the variables to be in any order and still get routed to the correct end location.
<?php
// Permanent redirection
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://www.example.com/{$_GET['id']}/{$_GET['cat']}");
I didn't do any error checking here, but wanted to give a base example.
On second thought I guess this is adding in functionality to the index.php file which you then want to use for your application itself, so perhaps it would end up confusing the functionality in the code.
I've been reading through a previous solution to a recursive mod_rewrite problem that is similar to what I'm trying to do, the difference is I'm sending all queries through an index.php file and so don't need to specify the script within the query.
Essentially I want to recursively convert any number of parameters within a search engine friendly url:
example.com/param1/val1/param2/val2/...
to a regular query string:
example.com/index.php?param1=val1¶m2=val2&...
So far I've been unsuccessful in in my attempts though:
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([^/]+)/([^/]+) $1=$2&%1 [L]
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ index.php?%1 [L]
Would anyone be able to offer any suggestions?
I copied the solution from that other question and modified it like this:
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*/)?([^/]+)/([^/]+) $1?$2=$3&%1 [L]
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^.*$ index.php?%1 [L]
It does nearly the same thing, except in the first rule, the first match is optional and in the second rule, the match is on whatever is left after all the other pairs are matched.
For an odd number of parameters, the first parameter is ignored.
One note, if you expect to have a lot of parameters, you may have to change some settings.
Add something like this to your .htaccess file
RewriteOptions MaxRedirects=20
and something like this to your apache conf file
LimitInternalRecursion 20
Instead of "20" pick whatever number of recursions (pairs) you need to allow (the default is 10).
I understand this is a very old thread. But since none of the answers posted here worked for me and I want to post my answer so that visitors can use it if they want so I am answering it here:
Options +FollowSymlinks -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)(/.*)?$ $3?$1=$2 [N,QSA,DPI]
RewriteRule ^(/[^/]+|[^/]+/|/?)$ /index.php [L,QSA,DPI]
For more details please see my answer on MOD_REWRITE for URL variables, removing empty parameters and using more than 1field for the first and second variables
yes...
Taken from the examples here:
http://iirf.codeplex.com/sourcecontrol/changeset/view/62027?projectName=IIRF#981491
This ruleset iteratively translates a pair of URL path segments to a querystring n=v segment.
# handle case with no query string. This rule fires the first time through,
# and converts the first pair of URL path segments to a n=v query string segment.
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)/([^\?]+)$ /$3?$1=$2
# handle the case where there is an existing query string, and more than one pair of
# URL path segments remaining. This rule fires potentially multiple times.
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)/([^\?]+)\?(.+)$ /$3?$4&$1=$2
# Handle the case with a query string, and exactly one pair of URL path segments.
# This fires once (last).
# It fires when there is an even number of segments.
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)\?([^\?]+)$ /help.cfm?$3&$1=$2 [L]
# Handle the case with no query string, and exactly one pair of URL path segments.
# This fires once (last).
RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)$ /help.cfm?$1=$2 [L]
# Handle the edge case, where there is an odd number of segments, which is invalid
# for these purposes.
#
# This fires once, after all the other pairs have been parsed. In fact the filter
# cannot know that there is an odd number of segments until it does all the matching.
# So at the end we see, we have one left over segment, and we
# redirect to a 404 page.
RewriteRule ^/(?!index\.php)([^\/\?]+)\?([^\?]+)$ /ResourceNotFound.php [L]
# Handle the edge case where there is only one segment. This is also an error
# in this ruleset.
RewriteRule ^/(?!index\.php)([^\/\?]+)$ /FoundOnlyOneSegment.php [L]
This ruleset might not be exactly what you want but it illustrates the approach. It was not developed for mod_rewrite, but for IIRF, which is a rewriter for IIS. But the syntax should be the same for mod_rewrite, so these rules should just work.
I don't know if mod_rewrite has a logging facility, or a command-line test capability, but IIRF does, which makes it easier to see how individual rules work, or the outcome of sets of rules.
IIRF has an iteration limit that defaults to 10. There's a way to raise that limit to 30, which is pretty high, but still not infinite. That means it won't work for "any number of parameters". It can convert up to 15 pairs of params. I don't know if mod_rewrite has a similar limit.
Try these rules:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^([^/]+)/([^/]+)(/(.*))?$ /$4?$1=$2 [N,QSA]
RewriteRule ^$ index.php [L]
The first rule is to exclude requests for existing files. The second rule will do the work and rewrite each name and value pair. And the third rule is to rewrite the final URI to index.php.