How do you hide something from the URL with htaccess - php

On my application i have a webshop with multiple items. For each item you are able to have different kind of colors. So the colors have to be in the url to send it as a parameter.
The moment you click on an item, you will get send to that item's page with the url http://cmsproject.local/item/2/nocolor. The nocolor is the thing i want to hide from the url, which would result looking something like this:
http://cmsproject.local/item/2.
If you have selected a color the last part of the url looks this "/2136c7". This is not a problem and should still be looking like this. Only when there is no color selected, the url should hide the nocolor part.
I have tried multiple forums, but none of them worked out for me. I have tried something like this:
RewriteRule ^2/nocolor/(.*)$ $1. and this
RewriteRule ^/2/nocolor [L].
My htaccess file looks like this:
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
RewriteRule ^/2/nocolor [L]
With this I expected that the url would "hide" the nocolor part, instead nothing changed and it didn't displayed any error.

If I understand your requirements correctly, I don't think you necessarily need to be handling this at the HTTP server level. From what I understand, you want a URL which can have an optional parameter as part of it.
Based on your example, my assumption is that the URL (with or without a color present) is handled by the same endpoint. So my suggestion is that you delegate that responsibility to the Laravel Router via optional route parameters.
Here's an example of how you could handle that, showcased with a simple route closure (this can of course be a controller action method):
Route::get('item/{id}/{color?}', function ($id, $color = null) {
// If the URL is "/items/2" then $color will be null
// If the URL is "/items/2/2136c7" then $color will be '2136c7'
});
Using the example above you can handle both situations.

You should do this in your laravel app, but in htaccess would the solution look like this:
RewriteRule ^/item/([0-9]+)/? /item/$1/nocolor
^ start of the match
? optional
+ at least one occurence
Take look at RegEx for further uderstanding.

Related

Rewrite Dynamic URL In PHP Using .htaccess

I wanted to rewrite url in following pattern
My current url is:
xyz.com/news_details.php?id=120&title=hello-world
and I want the url as is:
xyz.com/hello-world
also I wanted to fetch the values of id on this page like:
$id = $_REQUEST['id'];
please help
I did use the following code:
RewriteCond %{THE_REQUEST} /news_details.php\?id=([^&\s]) [NC]
RewriteRule ^ /%2\.html? [NC,R,L,NE]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^-])\.html$ /news_details.php?id=$2 [QSA,L,NC]
You could do something like this :
RewriteEngine On
RewriteRule ^/(.*)/(.*)$ /news_details.php?title=$1&id=$2
To achieve links like http://example.net/hello-world/120.
The ^/(.*)/(.*)$ part tells apache the pattern that it will follow. The second part (news_details.php?title=$1&id=$2) gives apache the real link that it will apply the pattern on.
You can't exactly hide arguments from the user, because you need a way to get the id that you want to have as the id argument. So that's the only possible way to do that.
You can read more about it here.

301 htaccess Redirect that will force?

Trying this again because I realize how very poorly I worded my original post.
I have a page, Product1.php, that is dynamic for populating my products from a database.
This is the rubric of my SEO-friendly urls:
http://www.example/category/subcategory/model_name-model_id/product_id
This is the original url with query string that it rewrites to:
http://www.example.com/Product1.php?=Product_ID=1
This is the rewrite function I have in htaccess that makes this happen:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/.*/.*/([0-9]+)$ Product1.php?Product_ID=$1 [L,QSA]
However, if a user manually-types in http://www.example.com/Product1.php?=Product_ID=1 in the address bar, this is the one they still see. Moreover, it's the same for the search engine bots, which is dividing the value of my pages.
How do I write a 301 redirect that will force the user and bot to see the SEO-friendly url only, regardless of how they access the page? I have researched for days and various solutions I have tried give me only 404 or 500 errors.
Please help. Thanks in advance.
**EDIT: OK, looks like I can't invoke RewriteMap because I don't have access to my host's config files. (Need to upgrade our account to do so and employer is unwilling.) So will have to do a Rewrite Rule for each individual page, which is unfortunate but doable.
But still need to find out how to force the redirect with causing 404 or 500 errors. Anyone?
I used a little trick adding an "Internal" parameter to a rule responsible for main rewrite, and the check of this parameter in the 301 redirect. The solution with environment variables is also allows to process requests where the parameters may be presented in any order.
RewriteEngine on
# perform collecting parameters from query string to an environment variables
RewriteCond %{QUERY_STRING} Category=([^&]+)
RewriteRule . - [E=category:%1]
RewriteCond %{QUERY_STRING} SubCategory=([^&]+)
RewriteRule . - [E=subcategory:%1]
RewriteCond %{QUERY_STRING} Product_ID=([^&]+)
RewriteRule . - [E=productid:%1]
#...etc...
# give a right 301 redirect
RewriteCond %{REQUEST_URI} Product1.php
# make sure it's not an internal redirect
RewriteCond %{QUERY_STRING} !^Internal=1(.*)$
RewriteRule . /%{ENV:category}/%{ENV:subcategory}/%{ENV:productid}/? [L,R=301]
# now rewrite rule with the additional "Internal" parameter to label it as an internal redirect
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ([^/]+)/([^/]+)/([^/]+)
RewriteRule .* Product1.php?Internal=1&Category=%1&SubCategory=%2&Product_ID=%3 [L]
Thus, the following request
/Products1.php?Category=cat1&SubCategory=subcat1&Product_ID=321
will result in 301 redirect to
/cat1/subcat1/321/
and the appropriate page will be shown.
One more way is to remove the "Internal" trick and use another name of the script, Products2.php for example. I.e. you need something to distinguish external request from internal rewrite. to avoid infinite loop ("too much redirects" error).

Mod_ReWrite regex unknown variables count?

i store uploaded files at /storage/ this way
public-adam-luki-uploads-123783.jpg
park-hanna-adel-propic-uploads-787689.jpg
the '-' count unknown because it slice the pic description
i want my users to be able to access it as
http://site.com/public/adam/luki/uploads/123783.jpg
http://site.com/park/hanna/adel/propic/uploads/787689.jpg
i think it is the same problem here
mod_rewrite with an unknown number of variables
but i can't do it because i'm new to mod_rewrite module
i hope you can help me guys with the right rewriterule
The question you link to doesn't actually do what you are trying to do (although the principle is the same) what they do is convert the url to GET variables.
If all you want to do is convert / to - then you can use a simple rewrite rule that will run in a loop:
ReWriteRule ^(.*)/(.*)$ $1-$2 [L]
There are of course a few caveats to that...
Firstly, even if you are trying to get to a real directory/file the rule will still switch out / and - and leave you with a 404. You can get around that by adding conditions; to stop it rewriting real files:
RewriteCond %{REQUEST_FILENAME} !-f
You would do better however to limit the matches to only images (jpgs):
RewriteCond %{REQUEST_FILENAME} !-f
ReWriteRule ^(.*)/(.*)\.jpg$ $1-$2.jpg [L]
Preferred Solution
ReWriteCond %{REQUEST_FILENAME} !-f
ReWriteRule ^images/(.*)/(.*)uploads[-/](\d+)\.jpg$ images/$1-$2uploads-$3.jpg [L]
RewriteCond %{REQUEST_FILENAME} !-f
ReWriteRule ^images/(.*)$ storage/$1 [L]
This solution requires you to use urls like:
http://site.com/images/park/hanna/adel/propic/uploads/787689.jpg
The pseudo directory images means you can be sure that the url is actually one that you want to redirect and it doesn't break other images/links on your site.
The above rules take a url (like the example above) and transforms it like so:
images/park/hanna/adel/propic/uploads/787689.jpg <--- Original
images/park-hanna/adel/propic/uploads-787689.jpg
images/park-hanna-adel/propic/uploads-787689.jpg
images/park-hanna-adel-propic/uploads-787689.jpg
images/park-hanna-adel-propic-uploads-787689.jpg
storage/park-hanna-adel-propic-uploads-787689.jpg <--- Final

URL parameters with PHP

Are there ways to pass variables in a URL similarly to GET data? For example, with slashes?
I currently have a single .php file which reloads a div with different content using javascript to navigate pages, but as you can imagine, the address in the address bar stays the same.
I want users to be able to link to different pages, but that isn't possible conventionally if there is only one file being viewed.
You're probably going to want to use something along the lines of Apache's mod_rewrite functionality.
This page has a nice example http://www.dynamicdrive.com/forums/showthread.php?51923-Pretty-URLs-with-basic-mod_rewrite-and-powerful-options-in-PHP
Try using:
$_SERVER['QUERY_STRING']; // Or
$_SERVER['PHP_SELF'];
If that doesn't help, post an example of what kind of URL you are trying to accomplish.
Something like this might do the trick;
place this in /yourdir/
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ yourindexfile.php?string=$1 [QSA,L]
All requests will be sent to yourindexfile.php via the URL. So http://localhost/yourdir/levelone becomes yourindexfile.php?string=levelone.
You'll be able to break down the string like so;
$query= explode('/', rtrim($_GET['string'], '/'));
the technology your looking for is .htaccess. technically this isn't possible, so you'll have to hack your mod rewrite to accomplish this.
RewriteRule On +FollowSymLinks
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(user)/([^\.]+)$ ./index.html?tab=user&name=$2
add this to your .htaccess page in your top directory. you'll have to alter your website structure a little bit. assuming that index.html is your index. this is a backwards rewrite so if one was to go to the page with the query string it won't redirect them to the former page and if one went to the page without the query string it will work like GET data still.
you GET this data with your php file using $_GET['tab'] and $_GET['name']
I think the Symfony Routing Component is what you need ;) Usable as a standalone component it powers your routing on steroids.
I'm doing it like this (in my like framework, which is a fork of the JREAM framework):
RewriteEngine On
#When using the script within a subfolder, put this path here, like /mysubfolder/
RewriteBase /mysubfolder/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
Then split the different URL segments:
$url = isset($_GET['url']) ? $_GET['url'] : null;
$url = rtrim($url, '/');
$url = filter_var($url, FILTER_SANITIZE_URL);
$url_array = explode('/', $url);
Now $url_array[0] usually defines your controller, $url_array[1] defines your action, $url_array[2] is the first paramter, $url_array[3] the second one etc...

.htaccess shorten URL using php $_GET

I need to be able to shorten my page from:
mydomain.com/mixtape.php?mixid=(WHATEVER NUMBER)
To:
mydomain.com/m/(WHATEVER NUMBER)
Now usually this wouldn't be much of an issue for me to figure out, but becasue of a few pre-existing functions in my .htaccess file, it is really hard for this function not to improperly interact with the others.
Below is the current code of my .htaccess file (AND NONE OF IT CAN CHANGE)
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ profile.php?user=$1 [L]
Above, the .htaccess file is shorting my
mydomain.com/profile.php?username=(USERNAME)
to
mydomain.com/(USERNAME)
Is there anyone out there than can help me by being able to shorten the m/index.php?mixid and not have it conflict with the pre-existing function?
Prepend this rule to your .htaccess block rewriting the profile url (after turning the rewrite engine on) :
RewriteCond $1 ^m/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ mix.php?id=$1 [L]
That rule will now only be used for URLS like :
mydomain.com/m/(WHATEVER NUMBER)
The first line is a condition that the incoming URL must start with m/
The second and third lines are conditions that the incoming URL does not represent an actual file or folder (we wouldn't want our humble rewrite rule to block us from a real resource).
The fourth line is the actual rule itself witch uses a regular expression syntax to match and capture everything that appears after host name and passes it to the mixtape.php file as a GET parameter called id. This line also contains the [L] flag which states that no more rules or rewriting will occur on the current incoming URL.
In your mix.php file you can use the explode method to split the resulting string into an array :
http://example.com/m/foo/bar =>
`http://example.com/mixtape.php?id=/m/foo/bar
$splitArr = explode('/',$_GET['id']);
$splitArr =>
array (
0 => 'm',
1 => 'foo',
1 => 'bar',
)
and remove the initial m with
array_shift();
Then you are left with $splitArr containing all the parts of your URL, split with a / (slash) delimiter.
The URL example.com/m/foo/bar would look like :
array (
0 => 'foo',
1 => 'bar',
)
It is important to place this rule before the existing one as the existing rule will act on any incoming URL. The final two rules that you have should appear like this :
RewriteEngine on
RewriteCond $1 ^m/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ mix.php?id=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ profile.php?user=$1 [L]
Regarding your statement :
AND NONE OF IT CAN CHANGE
I would seriously recommend that you consider implementing a small change on that first rule. Making the final url something like mydomain.com/users/(USERNAME) (as they do here). In these cases it is much better to be more specific than overly general (as the current rule is). Have you considered the confusion that could be created if someone was to chose a user name such as :
about
faq
home
While perfectly valid usernames these users profiles would be :
mydomain.com/about
mydomain.com/faq
mydomain.com/home
Those usernames will block important URLs that you might want to save for other locations on your site. I think it is clear why those user names would be undesirable.
RewriteRule ^m/([0-9]+)$ /mixtape.php?mixid=$1
Put in before or after the existing rule. Should not cause any conflict.

Categories