Apache mod_rewrite: differences between ^([A-Za-z\/]+)$ and ^(.*)$ - php

I really don't understand why my .htaccess file works wrong with ^(.*)$ ...
This is my .htaccess:
RewriteEngine On
RewriteRule ^(.*)$ index.php?alias=$1 [L]
I simply want to put all the text after my host address in the GET parameter named "alias".
The result of this, is that in my PHP script "index.php", $_GET['alias'] will have the value "index.php" instead what is after my host address.
If I change my .htaccess like this:
RewriteEngine On
RewriteRule ^([A-Za-z\/]+)$ index.php?alias=$1 [L]
I'll finally have $_GET['alias'] with the right value.
For example if I request http://myaddress.com/the-value-of-alias, in the first case I'll get $_GET['alias'] = 'index.php'. In the second case instead, I'll get $_GET['alias'] = 'the-value-of-alias'.
Then could someone explain me what are the differences between ^([A-Za-z\/]+)$ and ^(.*)$ please?
Thank you very much in advance. :)

When you put .* it matches any url so you end up in a recursive redirection whereas when you have specific regular expression elements it will work as it matches your first url only. It does not match the destination url as it has a 'equal-to' symbol in it

The ^(.*)$ expression means anything but a dot.
As for the expression ^([A-Za-z\/]+)$ it will get the Characters from A to Z as well as a to z

Related

What does the =$1 mean in url rewriting?

I can't find any information on stackoverflow or google about the meaning of =$1. I get superficial information but nothing for beginners like me. What does it do?
If I have something like this:
www.website.com/profile.php?simon
Does the name simon correspond to the $1 variable and why 1?
This is how I understand it:
(.*) profile/profile.php?id=$1
The bold corresponds to:
www.website.com/profile.php?id=simon
Converted with rewrite it becomes:
www.website.com/profile/simon
Am I missing something here?
Edit:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME}.php -d
RewriteRule ^(.*)$ /profile/index.php?id=$1
Does this change
localhost/test/index.php?philip
to:
localhost/test/profile/philip
I tried to enter the url but it failed. I understand what regex does but somehow im utterly confusing how the replacement works.
Backreference:
RewriteRule ^.*$ /?id=$1
$1 would be blank
RewriteRule ^(.*)$ /?id=$1
$1 would be whatever .* matched
RewriteRule ^(a|b|c)/(d|e|f)$ /?id=$1-$2
$1 would be either "a", "b", or "c", depending on which one matched, and $2 would be either "d", "e", or "f", depending on which one matched.
See: http://httpd.apache.org/docs/trunk/rewrite/intro.html#regex
One important thing here has to be remembered: Whenever you use parentheses in Pattern or in one of the CondPattern, back-references are internally created which can be used with the strings $N and %N (see below). These are available for creating the Substitution parameter of a RewriteRule or the TestString parameter of a RewriteCond.
Captures in the RewriteRule patterns are (counterintuitively) available to all preceding RewriteCond directives, because the RewriteRule expression is evaluated before the individual conditions.
Figure 1 shows to which locations the back-references are transferred for expansion as well as illustrating the flow of the RewriteRule, RewriteCond matching. In the next chapters, we will be exploring how to use these back-references, so do not fret if it seems a bit alien to you at first.
Does this change
localhost/test/index.php?philip to: localhost/test/profile/philip
No, It changes localhost/test/profile/philip to localhost/profile/index.php?id=philip. Assuming that the rule is in an htaccess file that is in your "profile" directory, then:
Browser types in or clicks on the link: localhost/test/profile/philip
The request is sent to localhost: /test/profile/philip
The request makes its way through apache's processing pipeline and mod_rewrite is applied to it, and the request is truncated to philip
Assuming that philip is neither a directory or file, the rule matches (.*) to it, and the string philip is captured
The rule then rewrites the request to /profile/index.php?id=philip
First, use Apache documentation rather than Google searches or Forums it's more helpful.
http://httpd.apache.org/docs/2.2/rewrite/intro.html#regex
And this
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond
Now (.*) is a parenthesized capture group in Regex. It says to match any single character and the asterisk means to repeat it 0 or more times.
When there is only 1 capture group. The numbered back reference is $1. Additional capture groups used or added will then be $2, $3 and so on.
For this example
www.website.com/profile/simon
You would get this rewrite rule.
RewriteRule (.*) profile/profile.php?id=$1
But your back reference $1 won't be simon, it will be profile/simon because you matched all characters requested using (.*).
If you only want to match simon you need to use a partial match like this.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME}.php -d
RewriteRule ^profile/(.+)/?$ profile/profile.php?id=$1
Then your $1 will only be simon and also the rule won't match any empty strings, meaning if there is no text after /profile/ it won't process the rewrite.
Let me try to explain in layman's terms.
Let's say you would normally link to a page like this...
/listing.php?id=2146_east_fifth_street
Then you create a rewrite rule like this...
RewriteRule ^([A-Za-z0-9_-]+)$ listing.php?id=$1 [NC,L]
This part ^([A-Za-z0-9_-]+)$ says to accept any querystring parameter with uppercase letters / lowercase letters / 0-9 / underscores / hyphens
This part listing.php?id=$1 says what page will be served up to the browser. the $1 asks for the first querystring parameter and appends it to the URL like this... your-domain.com/2146_east_fifth_street
That's what you see in the URL bar instead of... your-domain.com/listing.php?id=2146_east_fifth_street
EDIT
The second part of the rewrite rule is where the "real" page is located.
If you want your url to read /profile/philip
Your rewrite rule would start with /profile/ like this...
RewriteRule ^profile/(.*)$ path/to/the/real/file/index.php?id=$1
in .htaccess $1 is a back-reference to a group, usually from a regex statement.
Each group has its own reference, so a rewrite like
RewriteRule /profile/(.*)/([0-9]) /profile/index.php/$1/$2
$1 would equal the value of (.*) that group
$2 would equal the value of ([0-9]) which can only include numbers
and so on...
It helps when id numbers and url's are dynamic. So you do not need to manually add them one by one.
Example url:
website.com/profile/idealcastle/25555
And then in php or other languages, you can pull these "url segments". Just like using a "query" parameter, ?id=simon It's much better to use proper urls for SEO purposes.

Rewriting URLs with .htaccess

I am trying to convert urls like this http://example.com/page.php?user=x&post=x into
http://example.com/blogs/user/post
This is the code I have so far, not sure if I'm missing something or have done something wrong as it haven't been successful so far.
RewriteEngine On
RewriteRule ^blogs/([a-z0-9\-]+)/([0-9]{1,11})/$ page.php?user=$1&post=$2 [L]
EDIT: After making some amendments, it returns now an error 404 error saying page.php is not found. I know for certain the file is there.
2ND EDIT: Resolved 404 issue.
The post parameter is optional as well.
user can will have a mix of A-z0-9 (no character limit)
post can only be 0-9 with and upto 11 characters in length
According to http://htaccess.madewithlove.be/, this should work:
RewriteEngine On
RewriteRule ^blogs/([a-z0-9-]+)/([0-9]+)$ /page.php?user=$1&post=$2 [L]
This transforms http://example.com/blogs/abc_123/67890 to http://example.com/page.php?user=abc_123&post=67890.
The most notable change is that you apparently can't have a leading / in the first component of the rule, but I also removed the {11} constraint on the post ID since it's unlikely that would have the intended effect.
Try
RewriteRule ^blogs/?([a-z0-9]*)?/?$ page.php?user=$1&post=$2 [NC,L]
The ? indicates that the matching is optional. Therefore for /? the slash is optional.
And for the second section after the ^blogs/?
([a-z0-9]*)?
If you remove the ? and * from the above to become like this :
RewriteRule ^blogs/?([a-z0-9])/?$ page.php?user=$1&post=$2 [NC,L]
The user will no longer become optional and must be fully matched.
Example http://blogs/John;
If you put + in place of * like below:
RewriteRule ^blogs/?([a-z0-9]+)/?$ page.php?user=$1&post=$2 [NC,L]
The user need to be matched with at least 1 character. For example : http://blogs/J
And if you put * asterisk like below:
RewriteRule ^blogs/?([a-z0-9]*)/?$ page.php?user=$1&post=$2 [NC,L]
It can match to zero length. For example : http://blogs/ . Almost like optional.
If the match failed you will get the 404 Not found error
This code provides the desired results...
RewriteRule ^blogs/([a-z0-9]+)?/?$ page.php?user=$1 [NC,L]
RewriteRule ^blogs/([a-z0-9]+)?/?([0-9]+)?/?$ page.php?user=$1&post=$2 [NC,L]
I also amended the post ID constraint as Fraxtil pointed out.

Very simple RewriteRule doesn't work

I have index.php with only one line in it
<?php echo $_GET['a']; ?>
And also I have a .htaccess with only two lines in it
RewriteEngine on
RewriteRule ^([a-z]+)$ ?a=$1
Why when I enter /ab.cd I get a 404 error, but if I entering /abcd. it doesn't give me a 404 error and PHP echos abcd (without the dot on the end of the url).
Can anybody tell me why my rewrite rule allows abcd. through instead of giving me a 404 error?
The regular expression you've used, ([a-z]+), matches only the lowercase letters "a" through "z". It will never match a series of letters followed by a period followed by a series of letters, like your attempt with ab.cd.
If you want to match periods as well, you need ([a-z.]+).
EDIT:
I've just tested your Rewriterule (standalone) in my dev environment and it works. It doesn't allow /abcd. through on mine - It gives me a 404 error, so there must be something somewhere in your environment that's affecting your rules.
-initial post-
Looks like the period(.) in your /ab.cd isn't defined in the Rewriterule - just lowercase a-z chars.
Use:
RewriteEngine on
RewriteRule ^([a-z.]+)$ ?a=$1
^
I just rebuilt the situation on my server and I'm getting the desired 404 error. I only added the [L] flag to the RewriteRule.
.htaccess
RewriteEngine on
RewriteRule ^([a-z]+)$ test.php?a=$1 [L]
test.php
<?php echo $_GET['a']; ?>
Are there maybe any other rewrite rules following that might interfere with your request? Even in other files that get included? In that case, the L flag might help you.

URL Rewrite with htaccess and PHP

I have a URL: search/?word=asdf and want to redirect to: search/word/asdf/ and running internally: ?cmd=search&word=asdf
This so you can get the PHP $ _GET ['cmd'] and $ _GET ['word'].
How to do it in htaccess?
EDIT:
My .htaccess now is:
RewriteRule search(.*) %{HTTP_REFERER}cmd/search$1
RewriteRule cmd/search/?key-word=(.*) %{HTTP_REFERER}cmd/search/key-word/$1
But this not working. The new URL ever is:
localhost/bruc/sandbox/electrolux/trunk/cmd/search/?key-word=asdf
But it should be: localhost/bruc/sandbox/electrolux/trunk/cmd/search/key-word/asdf
So, I redirect this correct URL to: localhost/bruc/sandbox/electrolux/trunk/?cmd=search&key-word=asdf
But not working fine! Try, my approach here: http://htaccess.madewithlove.be/
Try RewriteRule ^([^/]*)/word/([^/]*)$ /?cmd=$1&word=$2 [L]. I believe that will accomplish your goal.
Try this :
RewriteEngine on
RewriteRule ^search/word/(.*)$ /?cmd=search&word=$1 [L]
Check this.
RewriteEngine on
RewriteRule ^([^/]+)/([^/]+)/([^/]+) /?cmd=$1&word=$2 [L]
There are three parts to this:
RewriteRule specifies that this is a rule for rewriting (as opposed to a condition or some other directive). The command is to rewrite part 2 into part 3.
This part is a regex, and the rule will be run only if the URL matches this regex. In this case, it says - look for the beginning of the string, then a bunch of non-slash characters, then a slash, then another bunch of non-slash characters. then again bunch of non-slash characters, then a slash, then another bunch of non-slash characters. The parentheses mean the parts within the parentheses will be stored for future reference.
Finally, this part says to rewrite the given URL in this format. $1 and $2 refer to the parts that were captured and stored.

Making wordpress like url by mod-rewrite

I am trying to edit the URL http://example.com/paper-ads-details.php?req=43674&rnd=1308632400 into http://example.com/ads/43674/1308632400 by following rewrite_rule
RewriteRule ^ads/([0-9]*)/([0-9]*)$ paper-ads-details.php?ads&req=$1&rnd=$2
But it's not working. I want to just hide the parameters. Any other suggestion will be appreciated. Thanks.
Both your rewrite rules make no sense. There are no $1 or $2 and what you are trying to do is impossible as no webserver can guess what the req and rnd parameters were.
You may be interested in rewriting http://example.com/ads/43674/1308632400 into http://example.com/paper-ads-details.php?req=43674&rnd=1308632400. Here is the code:
RewriteEngine On
RewriteRule ^ads/([0-9]*)/([0-9]*)$ paper-ads-details.php?req=$1&rnd=$2
If you want to rewrite: http://example.com/paper-ads-details.php?req=43674&rnd=1308632400 into http://example.com/ads?req=43674&rnd=1308632400, then try this:
RewriteCond %{QUERY_STRING} ^req
RewriteRule paper-ads-details.php?(.*)$ http://example.com/ads?$1 [L]
You can validate your rewrite-rule here - http://martinmelin.se/rewrite-rule-tester/
The question is quite confusing, made more so by the sample you provided, but if I understand correctly that you want the URL to contain no more parameters, then you won't have any $1 or $2 to work with. These would be the parameters that you match with your regular expression, but your regular expression doesn't match any parameter.
So, if you want /ads to go to /paper-ads-details.php?req=43674&rnd=1308632400, you can simply write a rule that does exactly that:
RewriteRule ^ads$ /paper-ads-details.php?req=43674&rnd=1308632400 [L]
The above rule will match the URL /ads and will call /paper-ads-details.php?req=43674&rnd=1308632400 every time that URL is requested.

Categories