I know how these kind of URLs load the page ... based on their GET parameter.
http://www.bedupako.com/songs.php?page=show_song_details.php&songid=1167&n=0&back=no
and in the back-end roughly something like this:
<?php
switch($_GET['page']) {
case 'xx': include('my page');break;
.
.
.
default: include('default');break;
}
?>
But how do these kinds of URLs work? I mean, how is the data loaded dynamically?
www.dummysite.com/parm/subpage1/xyz
www.dummysite.com/parm/subpage2/xyz
How are these parsed similar to the GET param like websites?
In most cases this will be handled by the web server on-the-fly according to a set of rules. The specifics of it will vary from server to server and on a case-by-case basis. In Apache it is usually done using the mod_rewrite extension.
You can use mod_rewrite by itself as others have suggested, but most sites do not do this because its not very flexible, and can be annoying to maintain if you have more than a couple of these "pretty" URLS.
Instead they set up a basic rewrite rule to forward everything to a single index.php and then on the application side they parse the URI based on defined patterns - these are called "routes". Route parsing usually happens in some kind of routing class which process the defined routes and compares them to the URI, and then when it finds a match parses out the parameters for the matched route.
These all provide good examples of a router, but they are hard to understand without the other interacting classes:
Zend: Zend_Controller_Router_Rewrite
Symfony: sfPatternRouting
Cake: Router
CodeIgniter: CI_Router
You should look at http://httpd.apache.org/docs/2.0/misc/rewriteguide.html url rewriting if you're with apache (most likely)
Related
First of all, I'm a beginner to PHP. And have posted a question here:
Refactoring require_once file in a project
. I've tried to read about Front controller as much as I can, but can't get how it works or even what's all about.
Can somebody explain in brief how it works and what's all about?
Front Controller refers to a design pattern where a single component in your application is responsible for handling all requests to other parts of an application. It centralizes common functionality needed by the rest of your application. Templating, routing, and security are common examples of Front Controller functionality. The benefit to using this design pattern is that when the behavior of these functions need to change, only a small part of the application needs to be modified.
In web terms, all requests for a domain are handled by a single point of entry (the front controller).
An extremely simple example of only the routing functionality of a front-controller. Using PHP served by Apache would look something like this. Most important step is to redirect all requests to the front controller:
.htaccess
RewriteEngine On
RewriteRule . /front-controller.php [L]
front-controller.php
<?php
switch ($_SERVER['REQUEST_URI']) {
case '/help':
include 'help.php';
break;
case '/calendar':
include 'calendar.php';
break;
default:
include 'notfound.php';
break;
}
With CodeIgniter I'm trying to create a URL structure that uses a title string as the entire URI; so for example: www.example.com/this-is-a-title-string
I'm pretty confident I need to use the url_title() function in the URL Helper along with the routes.php config folder but I'm stuck bringing it all together.
Where do I define the URI and how is it caught by the routes folder?
Seems to be a straight forward problem but I'm getting stuck creating the URLs end-to-end. What am I missing?
I thought about a catch-all in the routes folder: $route['(.*)'] = "welcome/controller/$1"; ....but how would this work with multiple functions inside a particular controller? ...and maybe it's not even the right way to solve.
You can send all requests to a driver with something like this:
$route['(:any)'] = "welcome/function";
Then use the _remap function to route requests inside the controller.
However, using URL's as you suggest limits the CI functionality. Try something better like www.example.com/article/this-is-a-title-string
$route['article/(:any)'] = "articles/index";
and in article (controller), use _remap...
If you're going to re-route every request, you should extend CI_Router.
The actual implementation depends on what you're doing. If you customize CI_Router, you can do it AFTER the code that checks routes.php, so that you can keep routes.php available for future customization.
If the URI contains the controller, function, and parameters, you can parse it within your extended CI_Router and then continue with the request like normal.
If the URI is arbitrary, then you'll need something (file, db, etc) that maps the URI to the correct controller/function/parameters. Using blog posts as an example, you can search for the URI (aka post-slug in WordPress) in the db and grab the corresponding record. Then forward the request to something like "articles/view/ID".
First of all, I'm a beginner to PHP. And have posted a question here:
Refactoring require_once file in a project
. I've tried to read about Front controller as much as I can, but can't get how it works or even what's all about.
Can somebody explain in brief how it works and what's all about?
Front Controller refers to a design pattern where a single component in your application is responsible for handling all requests to other parts of an application. It centralizes common functionality needed by the rest of your application. Templating, routing, and security are common examples of Front Controller functionality. The benefit to using this design pattern is that when the behavior of these functions need to change, only a small part of the application needs to be modified.
In web terms, all requests for a domain are handled by a single point of entry (the front controller).
An extremely simple example of only the routing functionality of a front-controller. Using PHP served by Apache would look something like this. Most important step is to redirect all requests to the front controller:
.htaccess
RewriteEngine On
RewriteRule . /front-controller.php [L]
front-controller.php
<?php
switch ($_SERVER['REQUEST_URI']) {
case '/help':
include 'help.php';
break;
case '/calendar':
include 'calendar.php';
break;
default:
include 'notfound.php';
break;
}
Let's pretend I'm trying to learn CI, and as my test project I am building a group-buying site.
What I'd like is to have a different page for each city, e.g.:
http://www.groupon.com/las-vegas/
http://www.groupon.com/orlando/
I'd also like to have different pages such as:
http://www.groupon.com/learn
http://www.groupon.com/contact-us
If I am building this in CI and following the MVC ideology, how would this work? I'm having difficulty seeing how to accomplish the desired URL's with the concept of:
http://www.domain.com/controller/view/segment_a/segment_b/etc...
What I would do is create a custom 404 controller that acts as a catch-all for non-existent routes.
It would take the URI, possibly validate it, and re-route it to the (e.g.) "city" controller.
If the city controller can't find the city (whatever string was specified), then it needs to issue a proper 404. Otherwise, you're good to display your information for that city.
Also, once you create your custom 404 controller, you can send all 404 errors to it by specifying a route named '404_override'.
That's where URI Routing comes in. But in your case you'll probably will have to be carefull defining your routes as the first and only part of your route is a variable part already.
This really has nothing to do with MVC, and much more to do with good URL.
You're looking for URLs that are both (a) clear from the user's point of view and (b) that give hints to your application as to how it's meant to be handled.
What I'd do in this case is redesign your URLs slightly so that rather than:
http://www.groupon.com/las-vegas/
http://www.groupon.com/orlando/
You would have URLs that looks like this:
http://www.groupon.com/destinations/las-vegas/
http://www.groupon.com/destinations/orlando/
The bit at the beginning--/destinations/--can be used by your URL routing code to decide what controller should be dealing with it. If your routing code is URL-based, you might have an array like this:
$routes = array(
'/destinations/' => 'on_destination_list',
'/destinations/(.+)' => 'on_destination',
'/(.*)' => 'on_page');
// Basic URI routing code based off of REQUEST_URI
foreach ($pattern => $func) {
if (preg_match("`^$pattern$`", $_SERVER['REQUEST_URI'], $placeholders)) {
array_shift($placeholders);
call_user_func($func, $placeholders);
}
}
Keep in mind that I wrote that routing code off the top of my head and it may not be absolutely correct. It should give you the gist of what you need to do.
Doing things this way has the added benefit that if somebody goes to http://www.groupon.com/destinations/, you'll have the opportunity to show a list of destinations.
The controller in a Java EE
application may be represented by a
servlet, which may be currently
implemented using JavaServer Faces
(JSF).
But in PHP there is no such servlet,so I guess is it implemented by url rewrite?
So that every request is directed to that controller?
It can be done with mod_rewrite but mostly in php there is a front-controller mechanisim which does all controlling through a single file. In this way, all controllers are specified in the url. See this for more explanation about controllers and mvc in php.
I think that's called the Front Controller pattern http://en.wikipedia.org/wiki/Front_controller and usually is achieved via mod_rewrite rules that any requests for phisically nonexisting files is redirected to index.php which then decides what to do.
MVC in PHP typically makes use of a front controller, which serves as the only entry point into the application.
This is usually implemented by using mod_rewrite to point all requests to a php file containing your bootstrap code.
This bootstrap code will contain your front controller.
The front controller takes it from there, redirecting the request based on the input parameters to the appropriate controller. Your target controller is usually specified as one of the parameters.
So, when you hit:
http://yourdomain.com/blog/new
The application would redirect the request to your bootstrap code with your front controller, which will interpret this input to mean 'blog' is the requested controller, 'new' is the action. It would then instantiate the 'blog' controller, pass it the 'new' action, and the rest is standard MVC.
As most of the other answers have shown, usually mod_rewrite is the way to do it. But, if you don't want to use mod_rewrite, you can let your bootstrap file actually configure variables from the URL itself.
I use a couple of my own functions which creates an array from a URL, so:
site.com/page/welcome/param1/param2
becomes
$url[0] = 'page'
$url[1] = 'welcome'
$url[2] = 'param1'
$url[3] = 'param2'
and then I can pass the $url array to my Router and it decides which parts of the Controller/Action/Param call each element belongs to.
The same URL request shown above creates the Controller/Action/Param call:
// http request for site.com/page/welcome/param1/param2
$controller = new Page_Controller('param1', 'param2');
$controller->welcomeAction();
while, depending on the settings in my Router object, I can create subdirectories, such as for calls to 'admin/':
// http request for site.com/admin/page/welcome/param1/param2
$controller = new Admin_Page_Controller('param1', 'param2');
$controller->welcomeAction();
With url_rewrite I think it would be harder (still possible though) to add those reroutes in, and with my method (Some frameworks might also do it, not too sure) it allows you to customize it more, ie you can edit the $url array if needed before passing it to the Router object.
I'm not sure what the negatives are in using this method, but it works pretty well for me!
You would use mod_rewrite to redirect everything to the index.php file. So you use mod_rewrite if you want this:
http://example.com/page/welcome
and not
http://example.com/index.php?page/welcome
or
http://example.com/index.php?controller=page&action=welcome