Important: ironically as it is, this thread was meant to sort out some confusion, but it turns out that I was one of the people who was confused. I can see now that I have mixed up the PageController and FrontController patterns. What I posted initially as PageController classes in this example, are what Martin Fowler in his Patterns of Enterprise Application Architecture (PoEAA) book refers to as Commands. I only recently bought this book and based on that decided to change this example. Everything named *PageController is now named *Command. The example is still valid, but the names are now compatible with Fowler’s definition of the patterns.
There has been a lot of interest in the MVC pattern lately and as a result of that a lot of confusion. People extending controllers from views, models acting as controllers: you name it and it gets mixed up around here
That’s why I would like to present a very simple example application that is structured using MVC and related patterns such as the FrontController. This approach is working for me and I have built a number of apps with it (can’t release the source of those unfortunately).
Some aspects of this example have been simplified, such as exactly how a form should be validated, as this is beyond the scope of the MVC pattern and only adds to the confusion. I also left out some implementations of the View classes, because they are also beyond the scope of the example. Nonetheless, I believe that the example demonstrates the different responsibilities of the objects involved here.
I’d be happy to hear you guys’ comments on it of course, just hopefully not questions as “Why aren’t you using a DAO?” because those have nothing to do with MVC.
Here goes:
/**
* The FrontController's job is to look at the incoming HTTP request
* to see what task the user of the application wants to perform.
* It will then create an object, which purpose is to handle that
* specific task: a Command
*
* For this example application, people can do the following tasks:
* - add a user account to the system => handled by the UserAddCommand
* - edit a user account => handled by the UserEditCommand
* - view a list of users => handled by the UserListCommand
**/
class FrontController
{
function run()
{
switch ($_GET['page'])
{
case 'add':
$command = new UserAddCommand;
break;
case 'edit':
$command = new UserEditCommand;
break;
case 'list':
$command = new UserListCommand;
break;
}
$command->execute();
$view = $command->getView();
$view->render();
}
}
/**
* This Command is responsible for the task of
* adding a user, and all the events that can occur while the user
* executes that task (submission of a form in this case)
*
**/
class UserAddCommand extends BaseCommand
{
function execute()
{
if (!$formHasBeenSubmitted)
{
$this->view = new UserAddView;
return;
}
if ($formIsValid)
{
$user = new User;
$user->username = $_POST['username'];
$user->password = $_POST['password'];
$user->email = $_POST['email'];
$user->save(); // could be $userDAO->save($user) or whatever
$this->view = new UserHasBeenAddedView;
}
else
{
// Redisplay the form
$this->view = new UserAddView($_POST, $formErrorMessages);
}
}
}
class UserEditCommand extends BaseCommand
{
function execute()
{
if ($userIsNotFoundInDatabase)
{
$this->view = new UserNotFoundView;
return;
}
if (!$formHasBeenSubmitted)
{
$this->view = new UserAddView;
return;
}
if ($formIsValid)
{
$user;
$user->username = $_POST['username'];
$user->password = $_POST['password'];
$user->email = $_POST['email'];
$user->save(); // could be $userDAO->save($user) or whatever
$this->view = new UserHasBeenEditedView;
}
else
{
// Redisplay the form
$this->view = new UserEditView($_POST, $formErrorMessages);
}
}
}
class UserListCommand extends BaseCommand
{
function execute()
{
$users = getUsersFromDatabaseSomehow();
$this->view = new UserListView($users);
}
}
class UserAddView
{
function render()
{
// Print a html form here
}
}
class UserHasBeenAddedView
{
function render()
{
echo 'The user account has been created succesfully.
Click here to return to the main page';
}
}
class UserEditView
{
function UserEditView($userObject)
{
$this->userObject = $userObject;
}
function render()
{
// Print a html form here and fill up the form fields
// with data from the $userObject
}
}
class UserListView
{
function UserListView($users)
{
$this->users = $users;
}
function render()
{
foreach ($this->users as $user)
{
echo ...;
}
}
}