Add dynamic query vars to all urls with .htaccess - php

I'm trying to add a query parameter to the end of all URLs on a site but that value needs to be dynamic.
RewriteCond %{QUERY_STRING} !(^|&)testing=true(&|$) [NC]
RewriteRule ^ %{REQUEST_URI}?testing=true [L,QSA,R]
This answer (code above) is very close to what I need, but I need 'true' to change based on the user provided value. An example would be various campaign ID's
http://domain.com/?campaign=32324
And when a user clicks on a link from this page, those links should append the ?campaign=32324
http://domain.com/somepage/?campaign=43454

If you want to append a query string to a URL, I believe this is what you're looking for.
Of course your parameter and/or its value can be populated in any number of ways. It can be passed from a previous page and populated by $_GET['something'] or provided by a DB query and populated from the results.
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^([A-Za-z0-9_-]+)$ your-page.php?your-parameter=$1 [NC,L] # Handle query string with no slash
RewriteRule ^([A-Za-z0-9_-]+)/$ your-page.php?your-parameter=$1 [NC,L] # Handle query string with a slash
The [A-Za-z0-9_-] portion allows a parameter value to include upper & lower case letters, numbers, underscore and hyphen. If all you want are numbers (as in your examples) simply remove everything between the square brackets except 0-9 like so... [0-9]

Related

How to add get parameters via htaccess?

How force add get parameter to url, that already have a get param? for example:
To url like this, which must have that ?a param, value doesnt matter:
example.com/?a=value
Make like this, value2 hardcoded:
example.com/?a=value&b=value2
I tried, yes its for index.php all:
RewriteRule index.php/?a$ /index.php/?b=value2 [L,R,QSA]
RewriteRule index.php/?a$ /index.php/?b=value2 [L,R,QSA]
The RewriteRule pattern (first argument) does not match against the query string. If you specifically need to check that the query string starts with the a parameter then you need a seperate condition that checks against the QUERY_STRING server variable.
Assuming your URL actually contains index.php (your example doesn't?) and the URL-path doesn't end in a slash (ie. contain path-info) then you could do:
# Check that query string contains the "a" URL parameter anywhere
# but does not contain the "b" URL parameter already (avoid redirect loop)
RewriteCond %{QUERY_STRING} \ba=
RewriteCond %{QUERY_STRING} !\bb=
RewriteRule ^index\.php$ /index.php?b=value2 [QSA,R,L]
The \b matches a word boundary, so a can only match at the start of the query string or at the start of a URL parameter (after &).
The QSA flag appends (ie. merges) the original query string from the request. So, it will redirect from /index.php?a=value to /index.php?b=value2&a=value - note that the original query string is appended.
If you specifically wish to keep the URL parameters in the original order and append the new value to the end then you could change the RewriteRule to the following:
RewriteRule ^index\.php$ /index.php?%{QUERY_STRING}&b=value2 [R,L]
Now the result would be /index.php?a=value&b=value2.

Get string from URL containing hyphen/dash (-)

I have tried to GET a string from a URL, for instance
'www.example.com/store/samsung-A5-2016'
I want to get 'samsung-A5-2016' from the link with the $_GET method, but all I 'get' is "Samsung".
I want to get the whole string 'samsung-A5-2016'.
You need to add the - at the beginning or the end of your character group so that it does not define a range:
RewriteRule ^store/([-0-9a-zA-Z]+) store.php?d=$1 [NC,L]
^ Here you can add the - sign
Note that this only allows for the - sign in your urls, if you want others, you need to add these separately too.
Please below rule for .htaccess
Because of currently your regex of .htaccess rule is not allowing '-' it gives string before the '-' of entire querystring value.
RewriteEngine on
RewriteRule ^store/(.*) store.php?d=$1 [L]

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.

.htaccess with products (string)

i use .htaccess and i have a rule that allow me to dynamically look for product in my database.
so someone can click on a link like this one:
www.domain.com/product/modular-plastic-lunch-set.html
and see the product. Now my problem is, when i use
www.domain.com/product/Modular-Plastic-Lunch-Set.html
it does not work,
why?
here's my rules:
RewriteEngine On
RewriteRule ^product/([a-z0-9\-]+).html$ products.php?name=$1
It does not work because you don't have either A-Z or the [NC] flag.
Use of the [NC] flag causes the RewriteRule to be matched in a
case-insensitive manner. That is, it doesn't care whether letters
appear as upper-case or lower-case in the matched URI.
RewriteRule ^product/([a-z0-9\-]+).html$ php.php?name=$1 [NC,L,QSA]
or
RewriteRule ^product/([a-zA-Z0-9\-]+).html$ php.php?name=$1 [L,QSA]
I added the L:
The [L] flag causes mod_rewrite to stop processing the rule set. In
most contexts, this means that if the rule matches, no further rules
will be processed. This corresponds to the last command in Perl, or
the break command in C. Use this flag to indicate that the current
rule should be applied immediately without considering further rules.
and QSA flag:
When the replacement URI contains a query string, the default behavior
of RewriteRule is to discard the existing query string, and replace it
with the newly generated one. Using the [QSA] flag causes the query
strings to be combined.
More information about the flags at: http://httpd.apache.org/docs/2.3/rewrite/flags.html
TIP: if you are looking for products using the name, you might see delay in your query, speically if you don't have an index. You should look into this before it gets ugly.
You're only looking for lower case letters (and numbers). You need to add upper case letters.
RewriteEngine On
RewriteRule ^product/([A-Za-z0-9\-]+).html$ products.php?name=$1

Htaccess Rewrite Rule Conditional

I am a complete noob when it comes to the .htaccess file... What I'm trying to do is check to see if a GET variable exists, ?si=10, and pass that onto the rewrite, but only if it exists.
RewriteRule ^user/([^/\.]+)/?$ profile/index.php?name=$1
This way when I have say website.com/user/Username/ it goes to, on the server, website.com/profile/?name=Username instead. But when I add do website.com/user/Account/?si=10, the server isn't passing the si variable onto the actually loaded page. Any idea how I would do this? Sorry if I worded this badly..
Try the QSA flag
RewriteRule ^user/([^/\.]+)/?$ profile/index.php?name=$1 [QSA]
From the manual...
When the replacement URI contains a
query string, the default behavior of
RewriteRule is to discard the existing
query string, and replace it with the
newly generated one. Using the [QSA]
flag causes the query strings to be
combined.
You can do it like this:
RewriteCond %{QUERY_STRING} ^si=([0-9]+)$ // replace regex as neccesary
RewriteRule ^user/([^/\.]+)/?$ profile/index.php?name=$1&si=%1
The percentage sign % brings in the match or matches from the rewriteCond(s) and you use the dollar sign as normal for the matches from the rewriteRule. This gives you full control of your query vars, but yes, QSA is simpler.

Categories