Rewriting url to hide index.php and to make query nice - php

I had developed project with custom MVC architecture. And I am new to Apache world, so I would appreciate help with this matter. On a Web I had found lots of tutorials, but no one like mine interests.
I have URL like this: http://knjiskicrv.comoj.com/index.php?page=book&id=1
I would like to be display like this: http://knjiskicrv.comoj.com/book/id/1
Or this: http://knjiskicrv.comoj.com/index.php?page=faq
Into this: http://knjiskicrv.comoj.com/faq
If there is no page in query (http://knjiskicrv.comoj.com/index.php), I would like to show: http://knjiskicrv.comoj.com/
Also with no page in query (http://knjiskicrv.comoj.com/index.php?category=2), it should be like this http://knjiskicrv.comoj.com/category/2
Hope someone will help. Thanks.

Actually, your problem is a two step proble. You first need to understand what is "Routing" in MVC. If you have your own implementation of an MVC like framework and you don't support routing, then it probably means you didn't even know how it worked before. (Sad but true)
In an MVC framework you setup routes using a ROUTER and the router analyses the urls for you saying HEY, i found this url that matches your request, go ahead and do work with it.
So then, your controller receives a request to route into itself and PARSES the url as he sees fit. Such as using explode('/', $_SERVER['REQUEST_URI']) and then reading the different parts of the url to map to expected variables.
All of this is very theoretical because there are ZILLIONS of way to implement it in a custom way. The only thing you will have to use is a little mod_rewrite magic to pass all requests to your index.php that will route everything. Look at the url below to learn about mod_rewrite, it's a VERY COMPLEX subject:
http://www.addedbytes.com/for-beginners/url-rewriting-for-beginners/
What i usually go for but i don't have access to it from home is something like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^assets/
RewriteRule .* index.php
This will redirect all traffic to index.php and you can then use $_SERVER['REQUEST_URI'] to analyze the request. Everything in assets/ folder will not be touched and work correctly.
Note, i built that part off my hat, it might not work...

Related

Dynamically create URLs

Something that is really confusing me is how sites have urls such as:
http://example.com/shop/
-and-
http://example.com/shop/product-category/games/
Originally, I thought you could simply just create a php file and use URL rewrite in the .htaccess. For example:
http://example.com/shop.php
http://example.com/shop.php/product-category.php/games.php (It just doesn't make sense).
Clearly, this is not the case as not only is it not efficient for more trailing slashes, but CMS's such as Wordpress automatically generate the content for the 'dynamic' URLs, and then redirect to a 301 page if the URL is not recognised.
I am wanting to implement this into my site, I'm just completely clueless on how I'd approach this. I am struggling to research deep into the topic due to myself being unaware what this system actually is. Obviously, I'm looking at this completely wrong, which is causing me to confuse myself.
If someone could explain to what this system is called, and how I can do it. I'd prefer not to get spoon fed code, I just need someone to explain it all too me.
EDIT: After some further researching, I have found a perfect example to make my question clearer. Notice this url:
https://gamurs.com/g/csgo/players
has the same url as:
https://gamurs.com/g/csgo
But shows different content, it's a completely new page, that is being 'dynamically' created.
Then more random URLs from the same site:
https://gamurs.com/articles/world-esports-association-announced
https://gamurs.com/coaches
Thanks,
Sutton
So certainly if you were to use a framework like Laravel, its a very easy way of having routing.
There is a "routes.php" file in every project that defines calls to a URL and responds with a controllers method. This will generally return a view.
It makes it as easy to create something like this as adding a line like this
Route::get('home', 'PagesController#home');
to your routes file and when you go to example.com/home it will fire the controller called 'PagesController' and run its home method. Within this method you could return a view that will be the page that you want to display.
This can be expanded in other ways.
You could have another route that is nearly the same but have another method for when someone sends post data to the same controller.
Route::post('home', 'PagesController#submittedhome');
So now you have another route that will take a post input to that page and fire a completely different method from the same controller. These kind of controls + many many more can allow you to achieve what you want really easily and is part of the core fundamentals of laravel.
Here is the Routing page on the laravel page that can illuminate you a little more.
There are many frameworks that use the term url rewriting but obviously not referring to .htaccess. Frequently it's called routing. WordPress does this by using page slugs.
In WordPress, .htacces sends requests for existing files and directories directly through, bypassing WP. Anything not matching as described above must be a "virtual" page. and is sent to index.php
The URI is then parsed in one way or another usually involving regular expressions. Each part of the URI path correlates to a "slug", these are then used to create a database query to generate the relevant content.
There's a lot more going on in terms of selecting specific templates for certain slug types.
A low tech approach to achieve the same outcome without requiring routing is to create a folder with the desired name, and have an index.php (or index.html) within it. Then when the url is called - the default is to open the index file within the folder, even if it is not specified in the URL.
therefore
http://example.com/shop.php/product-category.php/games/
would be the equivalent of calling
http://example.com/shop.php/product-category.php/games/index.php
Note that I am NOT advocating this (I think it would get messy very quickly and there are way more efficient solutions), nor am I suggesting that the given examples are doing it this way, but I wanted to post this because it is a viable method to producing url's without file names or indexes listed. Just not a very good one IMO.
If someone could explain to what this system is called
It's called RewriteEngine and it's part of apache mod_rewrite, other web-servers have different mods, but this the most popular.
RewriteEngine on
RewriteRule ^shop/$ shop.php [L]
RewriteRule ^shop/products/(.*?)/$ products.php?type=$1 [L]
The 1st example will display the content of shop.php when a user accesses www.site.com/shop/
The 2nd example will send games, as argument ($1), to products.php?type=$1, if a user access www.site.com/shop/products/games/
[L] - is called a flag (L|last):
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.
^ is relative to web root (somesite.com/^)
$ represents the end of the string (somesite.com/^somedir/test/$ this part will not be processed)
Resources:
Learn more about mod_rewrite and rewrite Flags

Is it Possible to Drop Uri Segments with Codeigniter Routing

I have the url: http://devsite.com/page/profile/11
I would like to retain the current functionality of /controller_name/method/profile_id
BUT, I would like the url to drop the controller name, so it would just be: method/profile_id
I'm thinking this is not what codeigniter uri routing is meant for. I understand to a degree and use uri routing all the time, but it seems that this is more of something I'd need to do with apache mod_rewrite or something? Any ideas are appreciated.
Thanks.
Small bug in your route. There shoud be $1 at the end, not $2:
$route['profile/(:any)'] = 'page/profile/$1';
I figured it out, I wasn't thinking about it correctly. I have not BUILT the application yet, rather I'm building it as we speak. So if I HAD built the entire application and I was just now asking this, it would indeed be an apache rewrite situation, but since I am building the app now, some "pre-thought" will save me the trouble.
Instead of linking to 'page/profile/id', I can just link to 'profile/id' and then in my routes.php put this:
$route['profile/(:any)'] = 'page/profile/$2';

Url representation in php

I am used to representing embedded url information like this:
http://test.com/reports/statement.php?company=ABC&q=1
how would I do it like this instead?
http://test.com/reports/ABC/Q1
You need to use Apache mod_rewrite to achieve this.
If your server has it enabled, you could do something like this in .htaccess:
RewriteEngine on
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ /statement.php?company=$1&q=$2 [L]
You can use $_SERVER['PATH_INFO'] to access anything in the URL docpath after the address of your script.
e.g.
http://test.com/reports/statement.php/ABC/Q1
...then in statement.php you would have the string "/ABC/Q1" in $_SERVER['PATH_INFO']
Of course, you'll need to setup your webserver to match the URL and target the correct script based on the HTTP request.
As stated by others, you have to use url rewriting.
Usually a php application that make use of it, it applies the pattern called Front Controller.
This means that almost every url is rewritten to point to a single file, where the $_SERVER['PATH_INFO'] is used to decide what to do, usually by matching with patterns you define for your actions, or return a 404 error if the url doesn't match any of the specified patterns.
This is called routing and every modern php framework has a component that helps doing this work.
A smart move would also be providing a tool to generate urls for your resources instead of handwriting them, so that if you change an url pattern you do not have to rewrite it everywhere.
If you need a complex routing system, check out the routing component of some major frameworks out there, e.g. Symfony2, Zend Framework 2, Auraphp.
For the simplest php router out there, check instead GluePHP. The codebase is tiny so you can make yourself an idea on how the stuff works, and even implement a small router that fits your needs if you want to.

Rewriting a CI url

I have never before rewritten a URL except for removing the index.php part of my CodeIgniter installs, and that I do by using a copy-pasted snippet in my .htaccess file. I haven't had the time to actually learn about what the snippet does; I'm basically very new to rewriting URLs.
I have a mobile version of my web application. I got as far as redirecting mobile users to a subdomain: m.myhost.tld. However, since I'm using (one) CodeIgniter (install), I have to send these mobile users to a mobile-specific controller, in my case /mobile/. So, the controller always shows up in my address bar.
I just don't think this is very clean, and I'm looking for a way to rewrite the URL; but truth be told, I'm not even sure if this is possible.. hence my question.
I want to get rid of the /mobile controller part. Is this possible?
Some examples:
My current mobile 'root' folder is
http://m.myhost.tld/mobile
I would like to turn this one into
http://m.myhost.tld/
At the moment, when I go to http://m.myhost.tld/, it redirects to the default controller for my CodeIgniter application, which is part of the 'desktop' version of the web app.
Another example:
Turning
http://m.myhost.tld/mobile#mobile/about
into
http://m.myhost.tld/#mobile/about
I'm not sure if I'm making any sense here. I am in my head, but like I said, I don't know what exactly is possible. If the user is on the m subdomain, I want to hide the /mobile part of my URLs. However, only when we're on the m subdomain, so the 'desktop' version (which sits at www ) does not get touched at all.
Like I said a couple of times now, I'm not sure what is possible and what I'm looking for might just be too complex or whatnot. I figured I would ask though, since learning by asking is what I do best. Please don't be too hard on me if this turns out to be a dumb question, sirs professionals ;)
EDIT:
I thought I'd edit because I don't want to come off wrong. I'm not necessarily looking for exact answers to my question. I also welcome documentation/tutorials/articles that might guide me to a solution. If I can manage to come up with a solution of my own, I will of course learn a lot more.
Thanks a lot.
This could be too simple of a solution but why not in your routing config do something simple like
in your config do something like
if ($_SERVER['SERVER_NAME'] == 'm.myhost.tld')
$route['default_controller'] = "mobile";
This would make the default controller mobil so you wouldn't have to have /mobile...
As i said maybe too simple
EDIT: Doesn't work, but maybe someone can turn it into something that does
Try this:
RewriteCond $1!^mobile/
RewriteCond %{HTTP_HOST} ^m\.myhost\.tld
RewriteRule (.*) /mobile/$1 [L]

Creating a RESTful API and website with PHP

I've got a PHP application I wrote earlier that I'd like to add a RESTful API to. I'd also like to expand the site to behave more like a Rails application in terms of the URLs you call to get the items in the system.
Is there any way to call items in PHP in a Railsy way without creating all kinds of folders and index pages? How can I call information in PHP without using a GET query tag?
If you have some form of mod_rewrite going you can do this quite easily with a .htaccess file.
If you have something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
It will check that the file you are trying to access doesn't exist already. (Say you had a file hello.html that you still needed people to access via http://yoursite.com/hello.html)
Then if the file doesn't already exist it will load your index.php file with the rest of the URL stored in the url variable.
This means you can call something like this http://yoursite.com/pages/edit/24 and it will load index.php with /pages/edit/24 inside the url variable.
That should get you started and you won't need all kinds of folders and index pages, just mod_rewrite, .htaccess file and an index.php that will be used to load whatever you need.
You also might consider to use one of the PHP frameworks with built-in REST support, for example CakePHP.
Quick note in respopnse to Pascal MARTIN: Zend_Rest_Server has absolutely nothing to do with REST. They just do RPC with slightly nicer URLs and call it REST so that it's more trendy.
If you want to do REST, you'll need to do a bit more work yourself as I have not found a good REST library for PHP yet. So inspect $_SERVER['REQUEST_METHOD'] to decide what to do with the called resource, etcetera.
Easiest way would probably using a framework that provides you with REST-oriented functionnalities. I know Zend Framework does that, with the class Zend_Rest_Server, that allows easy creation of a REST server.
I suppose many other frameworks do just the same.
But, if you already have an application that doesn't use a framework (or that is based on a Framework that doesn't embed that kind of class), a couple of URLrEwriting rules would do just fine ; you'd just have a bit more work to map URLS/parameters to classes/methods :-(
The design pattern you are looking for is called a front controller.
In its simplest form you use mod_rewrite to pass the incoming requests and pass it to a single php script. The url is then parsed with regular expressions and mapped to different response actions. However mapping an existing application may require extensive rewriting.
If you want to play around with this concept I recommend the Silex microframework.

Categories