What does the =$1 mean in url rewriting? - php

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.

Related

Redirect /api/ requests to /api/index.php with .htaccess [duplicate]

I am trying to Rewrite my mode using this info[copy from a website], but it's not working .. what's wrong with it and plz give a correct answer..
The Apache rewrite engine is mainly used to turn dynamic url’s such as www.yoursite.com/product.php?id=123 into static and user friendly url’s such as www.yoursite.com/product/123
RewriteEngine on
RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]
Another example, rewrite from:
www.yoursite.com/script.php?product=123 to www.yoursite.com/cat/product/123/
RewriteRule cat/(.*)/(.*)/$ /script.php?$1=$2
You seem to have misunderstood what the rewrite module (and your rules specifically) actually does.
Quite simply when you browse to:
localhost/abc/product.php?id=23
The RewriteRule isn't invoked and shouldn't be doing anything. There's nothing wrong here, you're just browsing to the wrong URL
URL Transformation
http://www.yoursite.com/product/123 <- URL that user goes to
http://www.yoursite.com/product.php?id=123 <- Rewritten URL that the server sees
RewriteRule(s) explanined
A rewrite rule is broken down into three parts (not including the RewriteRule part...)
The regex that it matches against the url
The url that it transforms into
Additional options
Given your rule:
RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]
The regex is: ^product/([^/.]+)/?$
The new url : product.php?id=$1
The options : [L]
This means that the user browses to the nice url http://www.yoursite.com/product/123 (and all of your links point to the nice URLs) and then the server matches against the regex and transforms it to the new URL that only the server sees.
Effectively, this means that you have two URLs pointing to the same page... The nice URL and the not-nice URL both of which will take you to the same place. The difference is that the not-nice / standard URL is hidden from the general public and others pursuing your site.
Regex
The reason why http://mysite.com/product/image.jpg is not being redirected is because of the regex that you use in your RewriteRule.
Explanation
^product/([^/.]+)/?$
^ => Start of string
product/ => Matches the literal string product/
([^/.]+) => A capture group matching one or more characters up until the next / or .
/?$ => Matches an optional / followed by the end of the string
Given the URL:
http://mysite.com/product/image.jpg
Your regex matches product/image but then it encounters . which stops the matching... As that isn't the end of string $ the rule is invalidated and thus the transform never happens.
You can fix this by changing your character class [^/.] to just [^/] or - my preferred method - to remove the character class and simply use .+ (seeing as your capturing everything to the end of the string anyway
RewriteRule ^product/([^/]+)/?$ product.php?id=$1 [L]
RewriteRule ^product/(.+)/?$ product.php?id=$1 [L]
Try
RewriteRule ^product/([a-zA-Z0-9_]+)/?$ product.php?id=$1 [L]

Removing the query string and redirecting (rewrite rule and rewrite cond)

I am currently trying to set up a rewrite rule to set up an internal redirect for a more SEO-friendly url-structure.
I want to show:
/find-teacher/primary-school.php
instead of the sad looking:
/find-teacher/subject-class-choose.php?school=primary-school
After I read some posts and tutorials about the rewrite rule and rewrite cond, I came up with this:
In my choose-school.php I have as a link with the nice looking url:
<a href="https://www.example.com/find-teacher/primary-school.php">
Primary School</a>
In my .htaccess:
RewriteCond %{REQUEST_URI} ^find-teacher/primary-school.php$
RewriteRule ^find-teacher/([a-z-]+)-([0-9]+).php$ /find-teacher/subject-class-choose.php?school=$1 [NC]
Now if I got that right, the RewriteCond part checks if the following url is requested. If that is the case, then the part of ([a-z-]+)-([0-9]+) is replaced by the $1 of the substitution part (/find-teacher/subject-class-choose.php?school=$1)
Problem is that I am redirected to my error page if I click on /find-teacher/primary-school.php
You don't need both a RewriteCond and a RewriteRule here, because they are (or should be) both checking the same thing.
However, currently, there is no URL which will match both patterns. Let's break down the problem.
To check specifically for the URL /find-teacher/primary-school.php, you could just write:
RewriteRule ^find-teacher/primary-school.php$ /find-teacher/subject-class-choose.php?school=primary-school [NC]
The next step is to "capture" the "primary-school" with ( and ), and place it dynamically onto the target with $1:
RewriteRule ^find-teacher/(primary-school).php$ /find-teacher/subject-class-choose.php?school=$1 [NC]
Finally, we can make the pattern match any letters or hyphens instead of an exact string, using the regex [a-z-]+:
RewriteRule ^find-teacher/([a-z-]+).php$ /find-teacher/subject-class-choose.php?school=$1 [NC]
In the rule in your question, you've added an extra part to the regex: -([0-9]+). This matches - and then a number. To capture that number, you'd put $2 somewhere in your target:
RewriteRule ^find-teacher/([a-z-]+)-([0-9]+).php$ /find-teacher/subject-class-choose.php?school=$1&id=$2 [NC]
This would match something like /find-teacher/primary-school-123.php, and turn it into /find-teacher/subject-class-choose.php?school=primary-school&id=123.
Two final notes:
depending how your Apache configuration is set up, you may or may not need to include the leading / in your patterns, i.e. start them with ^/
I find a nice way to debug rewrite rules is to make them redirect your browser, by adding R=temp to the flags (e.g. [NC,R=temp]); that way, you don't have to rely on your PHP code to tell you what URL was requested

Mod rewrite using .htaccess

I am trying to Rewrite my mode using this info[copy from a website], but it's not working .. what's wrong with it and plz give a correct answer..
The Apache rewrite engine is mainly used to turn dynamic url’s such as www.yoursite.com/product.php?id=123 into static and user friendly url’s such as www.yoursite.com/product/123
RewriteEngine on
RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]
Another example, rewrite from:
www.yoursite.com/script.php?product=123 to www.yoursite.com/cat/product/123/
RewriteRule cat/(.*)/(.*)/$ /script.php?$1=$2
You seem to have misunderstood what the rewrite module (and your rules specifically) actually does.
Quite simply when you browse to:
localhost/abc/product.php?id=23
The RewriteRule isn't invoked and shouldn't be doing anything. There's nothing wrong here, you're just browsing to the wrong URL
URL Transformation
http://www.yoursite.com/product/123 <- URL that user goes to
http://www.yoursite.com/product.php?id=123 <- Rewritten URL that the server sees
RewriteRule(s) explanined
A rewrite rule is broken down into three parts (not including the RewriteRule part...)
The regex that it matches against the url
The url that it transforms into
Additional options
Given your rule:
RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]
The regex is: ^product/([^/.]+)/?$
The new url : product.php?id=$1
The options : [L]
This means that the user browses to the nice url http://www.yoursite.com/product/123 (and all of your links point to the nice URLs) and then the server matches against the regex and transforms it to the new URL that only the server sees.
Effectively, this means that you have two URLs pointing to the same page... The nice URL and the not-nice URL both of which will take you to the same place. The difference is that the not-nice / standard URL is hidden from the general public and others pursuing your site.
Regex
The reason why http://mysite.com/product/image.jpg is not being redirected is because of the regex that you use in your RewriteRule.
Explanation
^product/([^/.]+)/?$
^ => Start of string
product/ => Matches the literal string product/
([^/.]+) => A capture group matching one or more characters up until the next / or .
/?$ => Matches an optional / followed by the end of the string
Given the URL:
http://mysite.com/product/image.jpg
Your regex matches product/image but then it encounters . which stops the matching... As that isn't the end of string $ the rule is invalidated and thus the transform never happens.
You can fix this by changing your character class [^/.] to just [^/] or - my preferred method - to remove the character class and simply use .+ (seeing as your capturing everything to the end of the string anyway
RewriteRule ^product/([^/]+)/?$ product.php?id=$1 [L]
RewriteRule ^product/(.+)/?$ product.php?id=$1 [L]
Try
RewriteRule ^product/([a-zA-Z0-9_]+)/?$ product.php?id=$1 [L]

Understanding a simple regex

I am developing a Symfony2 PHP application. In my Wamp server, the application is stored in www/mySite/ and my index.php is www/mySite/web/app_dev.php. Because/ of that, I have URL like 127.0.0.1/mySite/web/app_dev.php
I wanted to change the path so I acces my index file just by typing 127.0.0.1. After some research, I figured out that writting this .htacces in the www folder works :
RewriteEngine on
Rewritecond %{REQUEST_URI} !^/mySite
Rewriterule ^(.*)$ /mySite/web/app_dev.php
The only problem is that I don't understand why. Does somebody explain it to me ?
I don't really understand the two last line, and regex like ^(.*)$
Thanks
This is a simple regex indeed:
^(.*)$
Let's break it up:
^ - begging of a string
( and ) - capture group, used to match part of a string
. - any character
.* - any charactery any number of times
$ - end of a string
So, putting it all together, it means: "match any number of any characters". Later this matched part (part in parentheses) is replaced by /mySite/web/app_dev.php.
To explain regexes a little bit more we could imagine different regexes:
^lorem.*$ - string starting with word "lorem" followed by any number of any characters
^$ - an empty string
^...$ - a string containing three characters.
Now, putting it all together - Apache's rewrite rules are usually built of two directives: RewriteCond and RewriteRule. The latter directive will affect only those requests which match the condition given in the RewriteCond. You can think of them as a "if-then" pair:
# the "if" part - if request URI does not match ^/mySite
Rewritecond %{REQUEST_URI} !^/mySite
# the "then" part - then rewrite it to "/mySite/web/app_dev.php"
Rewriterule ^(.*)$ /mySite/web/app_dev.php
Rewritecond %{REQUEST_URI} !^/mySite
Check and make sure the requested uri does not("!") start with("^") "/mySite"
Rewriterule ^(.*)$ /mySite/web/app_dev.php
Then if that is true, take things starting with("^") any character(".") any amount of times("*") and send it to "/mySite/web/app_dev.php"
So a URI of /controller/site-action will be sent to that file while /mySite/css/style.css would not be.
Many places to check that will give a breakdown and explanation: http://regex101.com/
Regular expressions work character after character. In your `.htaccess it checks if the current URI matches the regex. In this image, follow the line character after character and it returns true:
^ and $ stand for the beginning and end of a string.
. allows any character and * tells to "repeat the last rule as often as possible".

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.

Categories