How to convert plus (+) sign to "=+" with htaccess? - php

I want to convert every url which contains "+" to "=+"
for example that url:
http://www.bedavaemlaksitesi.com/mersinemlakrehberi210/index3.php?+
should be like this:
http://www.bedavaemlaksitesi.com/mersinemlakrehberi210/index3.php?=+
tried that and few other lines but doesn't work so far, i'm guessing it causes a loop or something.
RewriteRule ^([^/\.]+)+([^/\.]+)?$ $1=+$2 [R]

I'm just gonna give you a literal answer for that specific example. Not sure if that will actually help you:
RewriteCond %{QUERY_STRING} ^([+])$
RewriteRule /index3.php$ index3.php?=(%1) [R,L]
You cannot repleace each + in the QS, as you do need a separate condition to match it first.
Also about your original rule:
RewriteRule ^([^/\.]+)+([^/\.]+)?$ $1=+$2 [R]
Escaping the dot in the charclass is redundant, [^/.] suffices. And you need at least a separator between the two groups / to make sense. But you can't match the query_string there, that's handled separately from the current filepath.
See alsos: ServerFault: Everything You Ever Wanted to Know about Mod_Rewrite Rules but Were Afraid to Ask? -and- HttpdWiki: Manipulating the Query String

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.

To Explode or RewriteRule? Utilizing Variables From Hyphenated URL's

I'm hoping I can make this make sense.
I had URLs' that looked like this
http://www.website.com/state/AZ/Phoenix
And now I've written them to this
http://www.website.com/AZ
using this rewrite code to parse (borrowed)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/.]+)(?:/)?$ /x.php?state=$1 [L]
RewriteRule ^([^/.]+)/([^/.]+)(?:/)?$ /x.php?state=$v1 [L]
RewriteRule ^([^/.]+)/([^/.]+)/([^/.]+)(?:/.*)?$ /x.php?state=$1&city=$2 [L]
This works great for parsing the "AZ" portion of the url and using it as a variable. Awesome. However, I wanted to take this to the next step and start using the city, and even crazier? not in the same order.
DESIRED URL FORMAT: http://www.website.com/phoenix-arizona-other-words
NOTE: I understand this doesn't say "AZ", it's fine, I'll convert the state to abbreviation through an array - the more important part is grabbing the first two words, separated by a hyphen and assigning them to variables.
For my code to work correctly I'll need to either find a way to explode the "-" in the URL and assign variables this way...
//my terrible attempt at fixing this the HARD way
$variables = explode("-", urldecode(substr($_SERVER['REQUEST_URI'], 1)));
$city = isset($variables[1]) ? $variables[1] : false;
$state = isset($variables[2]) ? $variables[2] : false;
or...
A RewriteRule could possibly save the day and understand what to do with the newly formatted URL and allow x.php? to utilize the correct variables, all while keeping the desired website.com/phoenix-arizona structure.
I think I'm close, basically, I need a Rewriterule to recognize hyphens and assign them to specific parameters, however I've been searching and tinkering around for over 4 hours on this before finally giving in! Any help would be appreciated, and if I'm not thinking about this correctly, it wouldn't surprise me as it's quite clear my regex (RewriteRule) skills are rudimentary at best and the explode function, if it even works, might be total overkill.
This rule should work to translate your PHP code into a rewrite rule:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^-]+)-([^/-]+)-(.+)$ /x.php?state=$1&city=$2 [L,QSA]
ok. I'll try to complete this answer tomorrow. But for the first rule, you might try with
RewriteRule ^([A-Z]){2}/? /x.php?state=$1& [L,QSA]
This means: match exactly two uppercase characters from A to Z, followed by an optional trailing slash and whatever comes next
This will turn
http://www.website.com/AZ
into
http://www.website.com/x.php?state=AZ
AND
http://www.website.com/AZ/whatever-url
into
http://www.website.com/x.php?state=AZ&whatever-url
Note that I have appended #anubhava QSA flag to append any query string after the slash to the rewrite rule. I could have captured that part with a wildcard (.*) too. I like his way more than mine.
States are easy because thanks to the USPS they all have kinda standard two character codes.
Edit: now for the second rule
RewriteRule ^([^-]+)-([^/-]+)- /x.php?statelong=$2&city=$1& [L,QSA]
will turn
http://www.domain.com/tucson-arizona-whatever-comes-next
into
http://www.domain.com/x.php?statelong=arizona&city=tucson&whatever-comes-next
Note that I inversed the captured items so I pass the second one to statelong. This way on your PHP you'll know that the state name needs to go through your dictionary array to get its standard USPS 2 character code.
Again, the "whatever comes next" gets appended thanks to the QSA flag. You'll need to capture that part with php by printing out the $_GET superglobal and looking for the orfan key.
Now, what happens when you get
http://www.domain.com/new-york-new-york-these-vagabond-shoes
Of course the rule won't work. Besides, the song was written when there was a New York County, roughly equivalent to today's Manhattan. (Irrelevant trivia).
The next is just an idea. I'm sure you can come with a more creative way
You need a way to tell cities from states from rest of the url. One way to do it is to use underscores to separate composite names, comma to separate city from state and hyphen for the rest.
This rule
RewriteRule ^([\w_]+),([\w_]+)- /x.php?statelong=$2&city=$1& [L,QSA]
will turn
http://www.domain.com/new_york,new_york-this-vagabond-shoes
to
http://www.domain.com/x.php?statelong=new_york&city=new_york&this-vagabond-shoes

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".

Apache RewriteRule rule

Alright, I give up. I just can't quite wrap my mind around apache rewrites, I've looked through a lot of the stackoverflow suggestions and none seems to make sense to me.
So, I have a script that current renders content based on www.example.com/index.php?article=some-article-name
But, I want the user to think that page is www.example.com/section/some-article-name
I've tried using stuff like
# Turn on URL rewriting
RewriteEngine On
RewriteRule ^/section/([a-zA-Z0-9\-]+)$ index.php?article=$1
I discovered the answer thanks to the direction of all of these folks.
RewriteRule ^section/([a-zA-Z0-9]+)$ test.php?article=$1
RewriteRule ^section/([a-zA-Z0-9]+)/$ test.php?article=$1
You need both to handle 2 different types of requests, ones with a / at the end and those that don't.
You may want a simpler rule like.
RewriteRule ^/section/(.*) index.php?article=$1
A name like some-article-name will fail because you won't match the hyphen. If you want a limited regex try something like:
RewriteRule ^/section/([-_.a-zA-Z0-9]+)$ index.php?article=$1
This will match ASCII alphanumeric characters along with punctuation most likley to be in the name.
Either of these rules will fail if you have parameters on the incoming request.
Your RegEx is SO close. You have a capturing group ([a-zA-Z0-9]+) that is looking for one or more lower case letters, upper case letters and/or numbers, but what it isn't looking for is a hyphen. Try this:
RewriteRule ^/section/([a-zA-Z0-9\-]+)$ index.php?article=$1
Because the hyphen has special significance in Regular Expressions you need to escape it.

Trouble with URL rewriting in .htaccess

My .htaccess file looks like this:
RewriteEngine On
RewriteRule ^articles/(\d+)*$ ./articles.php?id=$1
So, if the URL foo.com/articles/123 is requested, control is transferred to articles.php?id=123.
However, if the requested URL is:
foo.com/articles/123/
or
foo.com/articles/123/whatever
I get a "404 Not Found" response.
I would like to call articles.php?id=123 in all these cases. So, if the URL starts with foo.com/articles/[digits]... no matter what other characters follow the digits, I would like to execute articles.php?id=[digits]. (The rest of the URL is discarded.)
How do I have to change the regular expression in order to achieve this?
Just don't look for the end:
RewriteRule ^articles/(\d+) ./articles.php?id=$1
You do need to allow the trailing / with:
RewriteRule ^articles/(\d+)/?$
The \d+ will only match decimals. And the $ would disallow matches beyond the end.
If you also need trailing identifiers, then you need to allow them too. Then it might be best to make the match unspecific:
RewriteRule ^articles/(.+)$
Here .+ matches virtually anything.
But if you want to keep the numeric id separate then combine those two options:
RewriteRule ^articles/(\d+)(/.*)?$ ./articles.php?id=$1

Categories