How can I make my urls friendly from this example? - .htaccess

My site currently displays like this (when clicking on an ad):
hxxp://mysite.com/viewItem.php?id=10
I would LOVE for the urls to read:
hxxp://mysite.com/dogs/121/border-collie-for-sale-to-good-home
where "dogs" is forever a constant, 121 is always the $row['postId']; and "border-collie-for-sale-to-good-home" is always my $row['title'];
I know it probably won't be so easy as a quick answer here but would appreciate it if you could get me going in the right direction. I'm assuming a change to .htaccess is in order and I am just terrible at trying to decipher that.

Something that you can do is add a redirect at the top of the viewItem.php script. This redirect will need to check for a query parameter that you use to indicate that the .htaccess file as rewritten. Something like this:
if( !isset($HTTP_GET_VARS['rewritten']) ) {
// use whatever behind the scenes stuff you need to construct the friendly URL
$friendly_url = "http://mysite/" . getCategory() . "/" . getID() . "/" . getTitle();
// Now redirect the browser:
header("HTTP/1.1 301 Moved Permanently");
header("Location: $friendly_url");
exit();
}
// business as usual, the rest of your viewItem.php script.
So when this php script tries to handle a request that DOESN'T have the rewritten parameter in the query string, it redirects to the friendly version of the URL. If it DOES have rewritten it does what it usually does and handles the request.
Now in the .htaccess file, you want to rewrite the ugly URL to the friendly URL, but you need to include rewritten in the rewrite (I assume the "121" in your example is the "id" that the viewItem.php script takes:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^[^/]+/([^/]+)/ /viewItem.php?id=$1&rewritten=true [L]
If you leave out the &rewritten=true there, it's going to go into a redirect loop. You can also add a QSA in the brackets of the rule if you want to pass other query strings along with the rewrite in case you want to be able to handle friendly URLs like: http://mysite/dogs/121/border-collie-for-sale/?sort=asc With [L,QSA], the "sort=asc" gets passed along to viewItem/php.
So this is what happens now when someone clicks on an ad and gets taken to http://mysite/viewItem.php?id=121:
The browser location bar says http://mysite/viewItem.php?id=121 request is sent to mysite and viewItem.php is accessed
The top of viewItem.php sees that there is no rewritten param, so it redirects the browser to http://mysite/dogs/121/border-collie-for-sale
Since that was a 301 redirect, the browser's location bar changes to http://mysite/dogs/121/border-collie-for-sale
Request is resent to mysite but this time, the .htaccess rewrites /dogs/121/border-collie-for-sale to /viewItem.php?id=121&rewritten=true INTERNALLY, so the browser's location bar does not change.
The request makes it back to viewItem.php, this time, the script sees that there is a rewritten parameter, and does it's usual business and the request is served
You can use whatever name for the parameter flag you want, as long as none of the scripts are using it.

Related

htaccess redirect pretty URLs to ugly ones

So, I'm trying to make my URL's a bit more pretty and sharable. I have a website with some items that users can currently access with example.com/?i=itemName. However, I'd like users to be able to write example.com/itemName instead.
This means I'd have to do some redirection with htaccess. I want to redirect all URL's to example.com itself, but keep the URL the same. To clarify, an example:
User types example.com/niceItem. The server shows the content of example.com, but keeps the URL as example.com/niceItem (alternatively, it can change the URL to example.com/?i=niceItem, then I can simply read the URL with javascript and change it back to example.com/niceItem in the adress bar).
So far, this is the best I could do:
RewriteRule ^/([^\/]+)$ /index.php?i=$1 [NC,L]
The idea is to capture the requests that don't have slashes after the first one (like example.com/niceItem), and then read the file at example.com/index.php?i=niceItem. The problem is, when I load a page like example.com/niceItem, the page displays what the value of i is with php; it should be niceItem, as the link is supposed to be example.com/?i=niceItem, but the value of i is actually the string index.php. Not quite what I wanted. Also, I'd expect the following to work
RewriteRule ^/([^\/]+)$ /?i=$1 [NC,L]
but this actually causes an internal server error.
So, the question is, why do those not work, and how would I be able to achieve what I'm trying to achieve?
PS. Actually, this website I'm talking about is a subdomain of example.com. So, I have sub.example.com which maps to example.com/sub/, and I need the URL's to be prettyfied like sub.example.com/itemName or example.com/sub/itemName. As I mentioned, the format of the URL isn't that big of a deal as long as the itemName part is in there. I'll be able to read the URL with javascript and change it to whatever I want once the page has loaded.
Use RewriteCond
If i is the only query argument that will be passed then
RewriteCond "%{QUERY_STRING}" "(\?i=)(.*)$"
RewriteRule "(.*)/?$" "$1/%2"
If you need to extract i only but keep other query args
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))i=([^&]*)&?(.*)&?$"
RewriteRule "(.*)/?$" "$1/%2?%1%3"
Most every framework provides this sort functionality. It is best not to reinvent the wheel when possible. This is a fragile setup, and it will probably cause you headaches in the future.

How can I use mod_rewrite and preserve the url's fragment (anchor part)?

I'm taking a site that used to be static html (generated by an offline tool) and converting it to PHP. I'm sending all page urls to a single PHP file which parses the url. At first I just stuck FallbackResource MyPage.php in the .htaccess file, and it worked fine... except for urls with a fragment part. Many of the old urls were like /some-page.html#part2, and in the new scheme, part2 is a whole separate page, so I can't ignore that part of the url. With FallbackResource, all that MyPage.php would ever see is /some-page.html.
Now I've read some other questions on here about the topic, such as this one, and it seemed clear that mod_rewrite should in theory be able to do the job, but I can't get it to work. Here's my most current attempt:
Options +Indexes
DirectoryIndex MyPage.php
RewriteEngine on
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^:/.?#&]+\.html#(\w+) MyPage.php#$1 [NC,NE]
RewriteRule ^[^:/.?#&]+\.(html|php) MyPage.php [NC]
This works, again, for everything except anchors. It works no better than the old FallbackResource command did. I've tried juggling various parts of this in random ways, such as looking for %23 instead of #, omitting the NE flag, passing the value in a querystring instead of as a fragment, and whatnot.
I will note that I don't want to use redirection to translate the urls -- the PHP has to perform a lookup on it.
Well, I guess the answer is that it can't be done. The fragment part is never even sent to the server as part of the HTTP request. It stays inside the browser. Which means if anyone's saved an old link, it's just gonna go to the wrong page and that's all there is to it.
But I can write javascript into the page to redirect from the client. The PHP can iterate through the known list of old anchors on a given page and emit conditions to send them to the new page.

How to keep website available to some users oonly using htaccess

my website is under construction and i would like to show the website to my friends ,And deny to all users. i used particular ips in htaccess files,but ip is not static . Is there any way to keep mac address ? or any way
You can't match against a MAC Address using directives in an htaccess file. You could either
Put a password on your actual content and everyone without the password gets forwarded to an "Under Construction" page (possibly using ErrorDocument 403 /under_construction.html`)
Look for a special query string that you can give out to only your friends:
RewriteEngine On
RewriteCond %{QUERY_STRING} !special_var=my_buddies
RewriteRule ^ /under_construction.html [R=301,L]
So here, any url without the special_var=my_buddies query string ( http://hostname.com/some/content.php?special_var=my_buddies ) gets redirected to the under construction page
You can do something similar by setting a cookie. Create a small landing page called something like /my_buddies.php that simply does a set_cookie() call to create a my_buddies cookie (doesn't have to be php, and the cookie can be called anything). Then do something similar as the query string:
RewriteEngine On
RewriteCond %{HTTP_COOKIE} !my_buddies
RewriteRule ^ /under_construction.html [R=301,L]
Essentially the same thing. If there's no my_buddies in the cookie string, redirect to the under construction page.
There's probably other ways to get do something like this, but can't think of anything off the top of my head.

Simple ReWriteRule expanded with an anchor

Hi from Central Australia, Thankyou for your help
I have a simple re-write like this
RewriteEngine on
RewriteRule Trades-Services-(.*) Trades-Services.php?cat=$1 [L,NC]
what this does is turns the URL like this
http://website.com/Trades-Services-Plumber
into this
http://website.com/Trades-Services.php?cat=Plumber
what I hope for is to further (or compliment) that rewrite rule so it will turn this
http://website.com/Trades-Services-Plumber-123
into this
http://website.com/Trades-Services.php?cat=Plumber&ad=123#123
Where it throws on an anchor as well (#123)
the 123 could be any number and is always the same as the anchor
while still preserving that first functionality
it could also work with a URL like Civil-Celebrant instead of Plumber
e.g
http://website.com/Trades-Services-Civil-Celebrant-123
to
http://website.com/Trades-Services.php?cat=Civil-Celebrant&ad=123#123
Thankyou
To do the bulk of the rewrite, you'd need to change your existing rules and add the extra one to handle the second case:
RewriteEngine on
RewriteRule ^Trades-Services-(.+)-([0-9]+)$ /Trades-Services.php?cat=$1&ad=$2 [L,NC]
RewriteRule ^Trades-Services-(.+)$ /Trades-Services.php?cat=$1 [L,NC]
This should cover 3 of your 4 requirements, except for the first:
Where it throws on an anchor as well (#123)
The URL fragment, the #123 bit, is handled by the browser and when urls have a #name in it, the #name fragment is never sent to the server. So there's no way the server knows about the fragment, it's something the browser sees and the browser seeks to the anchor in the document. Something you could do is redirect to get the anchor. The first rule would then look like this:
RewriteRule ^Trades-Services-(.+)-([0-9]+)$ /Trades-Services.php?cat=$1&ad=$2#$2 [L,NC,R]
However, when someone enters http://website.com/Trades-Services-Plumber-123 in their browser's address bar, that rule will REDIRECT the browser to http://website.com/Trades-Services.php?cat=Plumber&ad=123#123, thus what's in their browser's address bar changes to the php URI. This isn't the same behavior you have in your original rule (which redirects internally on the server-side, preserving what's in the browser's address bar). The other thing you can do is when you generate links like http://website.com/Trades-Services-Plumber-123, ensure that there's a fragment added to it: http://website.com/Trades-Services-Plumber-123#123.

URL Rewriting based on form input

I'm creating a frontpage for my website with a single form and input text, Google-style. It's working fine, however, I want to generate a pretty URL based on the input. Let's say, my input is called "id", and using the GET method of form, and the action defined to "/go/", on submission, the URL will be:
site.com/go/?id=whateverIType
and I want to change it to
site.com/go/whateverIType
I was thinking on Mod Rewrite, but if the user put something in the URL, like:
site.com/go/?dontwant=this&id=whateverIType&somemore=trash
I want to ignore the other variables but "id", and rewrite the rule.
What's the better way of get this done? Thanks in advance!
PS: I'm using CodeIgniter, maybe there's something I can use for it as well. I already have a controller for "go".
I'm not familiar with CodeIgniter, but you can try the following RewriteRule
RewriteEngine on
RewriteCond %{REQUEST_URI} ^\/go\/
RewriteCond %{QUERY_STRING} id=([^&]*)
RewriteRule (.*) /go/%1? [L,R]
The %1 references the regex group from the previous RewriteCond, and the trailing ? will strip the querystring from the redirected URL.
Hope this helps.
Mod_rewrite supports conditions and rules with RegEx, so you could have a rule that matched the ?id=XXXX, that would extract it from the URL (keeping the other parameters), and rewrote the URL accordingly.
However... I don't think you want to do this, because if you rewrite the URL to be /go/Some+Search+Query, you won't be able to pick it up with say, PHP, without parsing the URL out manually.
It's really tough to have custom, SEO-friendly URLs with user input, but it is technically possible. You're better off leaving in the ?id=XXX part, and instead, using mod_rewrite in the opposite approach... take all URLs that match the pattern /go/My+Search+Terms and translate that back into something like ?id=My+Search+Terms, that way you'll be able to easily parse out the value using the URL's GET parameters. This isn't an uncommon practice - Google actually still uses URL parameters for user input (example URL: http://www.google.com/search?q=test).
Just keep in mind that mod_rewrite rewrites the URL before anything else (even PHP), so anything you do to the URL you need to handle. Think of mod_rewrite as a regular expression-based, global "Find and Replace" for URLs, every time a page is called on the server. For example, if you remove the query string, you need to make sure your website/application/whatever accounts for that.
In application/config/routes.php
$route['go/(:any)'] = "go/index/$1";
Where go is your controller and index is the index action.
http://codeigniter.com/user_guide/general/routing.html
You can use something like this in your .htaccess if you aren't already:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]

Resources