views:

43

answers:

4

I have setup two different PHP systems this summer. Each uses two different methods:

Method #1: One PHP File Per Task

This method requires that a PHP file be created for each major task. For example, my upload script would be access via http://www.domain.com/upload.php. On upload.php, a "controller" and a "view" class are instantiated and used. For example, upload.php might look something like this:

<?php
require_once PATH_LIBRARY . 'control/Uploader.class.php';
require_once PATH_LIBRARY . 'view/UploaderPage.class.php';

$uploader = new Uploader();
$uploader->setView(new UploaderPage());
$uploader->init();
?>

In the above script, if I wanted to call on another script, I would simply redirect and append the neccessary URL encoded variables (header('Location: edit_details.php?image_id=456');).

Method #2: A main index.php file that handles all requests

This method does not require that a PHP file be created for each major task. Instead, each "controller" class that will be used in the system is registered on index.php with a unique class that I call Router. The router decides if the specified Controller is legal or illegal and acts accordingly (routes the browser to the correct controller). For example, a simplified version of the index.php script:

<?php
require_once 'bootstrap.inc';
require_once PATH_LIBRARY . 'router/Router.class.php';

$router = new Router();
$router->register('Uploader', PATH_LIBRARY . 'control/Uploader.class.php');
$router->register('DetailsEditor', PATH_LIBRARY . 'control/DetailsEditor.class.php');
$router->route();
?>

Thus, every action takes place at index.php. There is no need for a lot of files which don't do much else that instantiate a specific view and controller class. BUT, if you want to call script/class A from script/class B, then you need to pass the controller class's name along on the URL: header('Location: index.php?controller=DetailsEditor&image_id=456').

So far, I don't really like the fact that I need to include the Controller name in the URL. I feel that it exposes too much of my underlying system to the end-user. But, I do like the fact that I can register all controller classes on one page. Mostly, I don't know if exposing the controller name is safe or not. One other annoyance is that, if I want to call on a script via POST requests, I have to include a hidden input that specifies the required controller class (e.g. <input type="hidden" name="controller" value="DetailsEditor" />).

I hope that is enough to go on. I am just nervous that the second method is not really going to serve me well in the months ahead. I have a small window of time soon to choose one or the other.

Thank-you.

+1  A: 

Handling with Router is more efficient, because You have only one place to change, if You'll be forced to change file/dir structure in a future, and if any collaborators will come, its much more easy to understand how system works if every loads is done by just one "router/algorithm"

Just my opinion

PS imagine if You'll have to change dir structure, You'll be forced to rewrite a bunch of includes, witch is time consuming, and can produce mistakes, and takes time :)

canni
+2  A: 

If you use the second option you should use URL rewriting to turn the URLs into a nice, human-readable format. That way gives you flexibility and power - definitely the way to go. This method is generally called a front controller, btw.

Skilldrick
+1  A: 

The front controller is nice b/c you avoid all of those simple script files, and it also gives you lots more flexibility. In this method, you don't have to specify the controller name in the url, as long as the Router has a way to find the correct view.

My advice would be to use the Router class to generate your links, too. That way, instead of

header('Location: index.php?controller=DetailsEditor&image_id=456')

your redirect would look like

$router->redirect ($router->getUrl ('editimagedetails', array(456)));
// example getUrl method signature is     
//    string getUrl (string $viewOrActionName, array $params)

Naturally, getUrl would be used to generate links and form action urls as well.

Any changes (say turning URL-rewriting on or off or renaming query string parameters) involve only the Router class because the name DetailEditor and the query string parameter image_id are implementation details unknown to the client code.

grossvogel
A: 

Not so fast. The approach with one PHP file per action can be faster and better. It depends on how you set things up.

  • The web server will route the HTTP request to the correct handler based on the filename. Why reinvent that?

  • Most times, all you need for a "handler" is:

    <?php include "everything.php";
    // do some work
    // Bounce the browser to a "view" url or display an error.
    

    which is all at least as concise.

Ian
@Ian - Would you comment on the issue of dealing with URL-rewriting? @grossvogel mentions this in his answer. Thanks!
letseatfood
Well, the big thing is that URL rewriting is an administrative task -- you have to set up the web server to cooperate. Also, it can be easier to correlate maintenance requests with files than with rewritten URLs. That's why I tend toward the "many small scripts, big include area" approach.
Ian