To hopefully clear up some MVC confusion

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 :slight_smile:

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 ...;
        }
    }
}
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
 	}
 }
 

Is userObject from your Model Layer? I would prefer to send this info in a dataset… or at least using a hash. Would’nt you?

Switch/cases can quickly get very large. Dynamically invoking PCs can be a good option.

  Following class also uses a CommandReader which parses a custom url format.

       class FrontController
       {
       	function FrontController(&$command_reader)
       	{
       		$this->command_reader =& $command_reader;
       	}
       	
       	function execute()
       	{
       		$this->module   =  $this->command_reader->getModule(); 
       		$this->command  =  $this->command_reader->getCommand();
 		 $params		 = $this->command_reader->getParams();
 		 $class		 = $this->_selectPC();
 		 $command		=& new $class($this->module
 										 , $this->command
 										 , $params
 											 );
       		
       		$command->execute();
       	}
       
       	/*
       		Command dictionary check.
       		return (string) - a class name
       	*/
       	function _selectPC() 
       	{
 		if(@include('modules/' . $this->module . '/rc/' . $this->command . '.php'))
       		{
   			return ucfirst($this->command) . 'PageController';
       
       		} else {
       		
 			 include('modules/invalid_requests/rc/invalid_command.php');
       			return 'InvalidCommandPageController';
       		}
       	}
       
       }
       

PS: sorry I can’t seem to get this indented properly.

Is userObject from your Model Layer?

It’s the constant niggling questions like that that deter me from ever going near MVC. Any kind of coding structure that causes this much confusion over so many minor details must be going wrong somewhere.

Thanks, Captain Proton. This code example is exactly what I have been looking for. I’ve been reading and studying so much about MVC and PHP the last couple of weeks that I couldn’t keep anything straight. This helps a lot!

My only question is about the base PageController and what should be in it? An example skeleton or psuedo-code of what should/could be in a base PageController is something that I have, as yet, been unable to find. Any directions would be greatly apprciated.

Peer

Anything common to all the PCs - starting a session & authentication for example.

Captain Proton,

Thanks for the post. I have a few questions about your specific implementation. Why do you invoke Page Controllers from your Front Controller? Doesn’t that defeat the purpose of having a Page Controller in the first place? If Page Controllers are used, the Web server should act as the Front Controller. Instead, I would have a set of Command (or Action) classes (e.g. ViewNewsCommand, AddNewsCommand, UpdateNewsCommand, DeleteNewsCommand, etc.) and leave the Page Controllers out all together unless you are trying to reuse the Page Controller functionality somewhere else. These two patterns can certainly live together, but I have never seen one invoke the other or vice-versa.

For a Front Controller implementation, usually we will have URL’s of the following form:

http://www.sample.com/index.php?command=ViewNews

or

http://www.sample.com/index.php/command/ViewNews

The Front Controller gets the ‘ViewNews’ from the URL and creates a ViewNewsCommand which it invokes. If news is available, the ViewNewsCommand chooses the NewsView, otherwise the ViewNewsCommand chooses NoNewsView.

The Page Controller version, although extremely similar, uses the Web server as the Front Controller and would have a URL like this:

http://www.sample.com/viewnews.php

Inside viewnews.php, we would create a ViewNewsController object which would have virtually identical functionality to the ViewNewsCommand object. I prefer this method primarily because PHP recreates its environment upon every request. If I was using Java Servlets, I would most likely go for the Front Controller instead.

Obviously, a particular application could use both of these patterns, but I do not see them interacting because of their distinct differences.

Thanks,

JT

Is userObject from your Model Layer? I would prefer to send this info in a dataset… or at least using a hash. Would’nt you?
Yep, $userObject comes from my model layer. When you say you’d like to send it as a hash, do you mean an array like array(‘username’ => …, ‘password’ => …, etc) or an array like array(‘user’ => $userObject)? If you mean the first, then, well, I guess it’s a matter of personal preference. You could pass the View an array instead of an object, the important thing is that it’s some model data.

Switch/cases can quickly get very large. Dynamically invoking PCs can be a good option.
Completely agree. The switch statement was merely an example. For the app I’m developing now I use something like what you describe. But then again, the example was simply to illustrate what a FrontController should do. The actual implementaion of how that is done is up to the developer’s creativity (or the framework writer :)).

It’s the constant niggling questions like that that deter me from ever going near MVC. Any kind of coding structure that causes this much confusion over so many minor details must be going wrong somewhere.
That’s because MVC does not say anything about this question: it leaves it up to you, the developer, to decide this to your best ability. MVC doesn’t care about that, because that is not what the pattern is for.

My only question is about the base PageController and what should be in it? An example skeleton or psuedo-code of what should/could be in a base PageController is something that I have, as yet, been unable to find. Any directions would be greatly apprciated.
Here’s something that would fit in with the example code:

class PageController
{
	var $view;
	
	function execute();
	
	function getView()
	{
		return $this->view;
	}
}

Anything common to all the PCs - starting a session & authentication for example.
How common are those things to all Page Controllers? For the public section of a website, you don’t need to authenticate users, right? I personally prefer to implement sessions & authentication through the use of InterceptingFilters. The FrontController can set these up. But you can achieve the same thing by having multiple PageController base classes: one for pages that do need authentication, one for those that don’t need authentication, one for those that need authentication and sessions, one for those that only need sessions… see why a chain of intercepting filters might be more flexible?

Why do you invoke Page Controllers from your Front Controller? Doesn’t that defeat the purpose of having a Page Controller in the first place? If Page Controllers are used, the Web server should act as the Front Controller. Instead, I would have a set of Command (or Action) classes (e.g. ViewNewsCommand, AddNewsCommand, UpdateNewsCommand, DeleteNewsCommand, etc.) and leave the Page Controllers out all together unless you are trying to reuse the Page Controller functionality somewhere else. These two patterns can certainly live together, but I have never seen one invoke the other or vice-versa.
You are essentially right. My FrontController is not one in the strict sense of how Martin Fowler describes it. What Fowler proposes is that a FrontController invokes commands on the model of the application and contains the logic for choosing a view. Fowler’s FrontController is essentially a mix of the potentially large switch statements of my FrontController plus the logic for choosing a view that you find inside each PageController.

A ViewNewsCommand is not the type of command that the FrontController would invoke, that is not a domain model command. Domain model commands are independent of the presentation layer on top of it. They are things like CalculateInterestRatesCommand and MakeSSLPaymentCommand.

The code that you probably have in ‘ViewNewsCommand’ is probably something like this: create a DAO, find a News object by id and create a View object to display that news. When you follow Fowler’s FrontController pattern, this code would be implemented inside the FrontController itself with the help of something like a GetNewsCommand. Now this may not seem like a big difference, but trust me, it is. GetNewsCommand is independent of the kind of presentation layer involved (it only loads a News object from the DB, no view choosing whatsoever), while ViewNewsCommand is not: it knows what View object it must create to display the news.

The Page Controller version, although extremely similar, uses the Web server as the Front Controller and would have a URL like this:
Alright, you could use the web server as the front controller (which isn’t a true front controller either, by the Martin Fowler pattern). But you loose all the advantages that a FrontController in combination with PageControllers can give you:

  • the ability to (dynamically) run Object Oriented!InterceptingFilters before passing on the request to a PageController instead of messing with auto_prepend_files and auto_append_files
  • you can change the URL naming scheme of your website from something like index.php?page=whatever to /site/whatever by making a change in the FrontController instead of messing around with mod_rewrite for all page controllers
  • have a central entry point for all the requests to your application. This is important to make the code readable and understanable, a clear structure of the ‘flow of a request’: from the FrontController possibly through the InterceptingFilters to a PageController. This instead of having to wade through if/else statements in auto_prepended files and to be unsure if control needs to be passed back to the actual requested page, redirected somewhere else, etc.

Notice how a combination of a FrontController and PageControllers is the Object Oriented equivalent of the procedural and messy combination of a web server, auto_prepend and auto_append files and possibly mod_rewrite? Since we are talking about a Design Pattern here, Object Oriented, I’d say that it makes sense :slight_smile:

Front Commands (those commands invoked by a Front Controller) and Domain Commands (those invoked by an Application Controller) are not the same thing. ViewNewsCommand is a valid command as it is the representation of a user’s request to view the news. This is presentation layer stuff not domain layer stuff. I think we are simply looking at the problem from two different perspectives. I am looking at it from the user’s perspective. What does the user want to do? View the news? Update a news item? Well, IMHO, these are “Commands” which a front controller would invoke. They may ultimately lead to updating the state of the model or invoking one or operations on the model or they may simply request the state of the model as with “ViewNewsCommand”. On the other hand, I think you are looking at it more from the application perspective. What does the application have to do (in resonse to a user request)? Get the news items? It is a subtle yet important difference in our perspectives. Which way is “correct”? I cannot say. To some people, your way may make a lot more sense than mine.

JT

Jeepers Creepers, now I am really going to get some therapy. :slight_smile: Each post keeps me changing my opinion on what I should do. Personally, I preferred not to use Front Controllers (I think Harry’s article about them started me down that path), but this last post is has a excellent argument for them.

As a result, I would like to know more about Intercepting Filters. I have seen lots of posts talking about using them, but no information about them. Anyone got any references that you could direct me to?

Peer

@pallan: Have a look at the stickied thread Advanced PHP Resources by Harry, there is some useful link for intercepting filters there. :slight_smile:

Just to confuse you further, it is possible to put just about all of the FrontController code (eg intercepting filters) into a base PageController class.

The webserver-duplicating role has to stay in the FC, of course. A slim FC like this isn’t completely pointless. There’s a minor convenience with relative paths (the current working directory is always the same, ie wherever you installed index.php). Similarly, cookies are always set in root which might save you having to merge validation rules for root cookies with any additional cookies which might be set in whatever directory the current PageController is in. Neither makes a particularly strong case for a FrontController - but then a FC shouldn’t create any real penalty either.

Yes, it should be theoretically possible to put intercepting filter code into a base PageController class, however, it seems to be much easier to do this and to chain actions when you are using a FrontController setup. Hence, why they recommend it. I haven’t tried implementing a PageController with intercepting filter, I’ve always just gone to a front controller in that case. Might be interesting to try out…

JT

After re-reading the PoEAA chapter on Web Presentation Patterns, I am convinced that there is NOTHING you can do with this combination of Front Controller and Page Controller that you cannot do with Front Controller alone. Also, Front Controller and Intercepting Filters are a natural fit:

<snip/>

JT

Yes, an array like array(‘username’ => …, ‘password’ => …, etc).

The thing is that I am not confortable letting the presentation layer to run business logic. For example, if I send the whole UserObject to the view I might be allowing someone else to run methods from the user object IN the view. A work that I would prefer to do in the controller.

If I find myself provided with a UserObject (from the Model layer) in my presentation logic, I am aware that I’ve been provided with this object to get the Domain data I want to display … just that. But still the object lies there with a lot of methods that you won’t use, or at least you should not, BUT you cant enforce it.

The point I am getting at is that sending this Domian Object to the View might lead to tightly coupling both layers, which kinda defeats the purpose of the pattern. IMO, using some kind of Data Transfer Object will clear the View from the responsability of executing any Domain Logic. The view just needs the data to be displayed.

One more thing, using a Data Transfer Object will help you do tests on your View objects since you can fill the DTO with some dummy data, giving the layer a certain kind of independency for testing, if the other ones are not ready.

Cheers,
Andres

Fowler talks about using a helper:

class User {
    var $id;
    var $name;
    function getId() {
        return $this->id;
    } 
    function getName() {
        return $this->name;
    } 
    // All of your setters aswell.
    // This would contain all of you domain logic functions aswell
} 
// Helpers only have functions relating to the view
class UserHelper {
    private $user;
    function UserHelper(User $user) {
        $this->user = $user;
    } 
    function getName() {
        return $this->user->getName();
    } 
    function getId() {
        return $this->user->getId();
    } 
} 

$user = getUserFromDatabaseSomehow();
// Carry out domainLogic
$this->view = new UserEditView(new UserHelper($user));

Of course before you use a domain object like User you probably should have some sort of domain logic, otherwise a dataset/resultset would work the same.

This is all starting to make more sense to me. Thanks everyone. Naturally, I do have another question :slight_smile:

When using a Front Controller would you recommend only using the one page access point (eg .index.php)? Or would it make any sense to have a FrontController for each section of your site (eg. UserFrontController, NewsFrontController, etc)? I ask because I can see the switch statement getting rather large in a single access point for a big site and this would seem to break it up into logical units.

Peer

It depends. I’ve seen it both ways. I believe that the intention of the PoEAA Front Controller pattern is to have one single entry point into the application. However, the seminal paper on MVC for Smalltalk describes mutliple controllers which manage related operations. I guess it is up to the developer in terms of how they want to partition their application.

JT

Seratonin, alright, but then I don’t even see the difference between your Commands and my PageControllers, except the name of course.

does the user want to do? View the news? Update a news item? Well, IMHO, these are “Commands” which a front controller would invoke
… and …
however, it seems to be much easier to do this and to chain actions when you are using a FrontController setup.
I assume chain actions are a chain of Commands? If so, if you use Commands for things like session tracking you might ask yourself this question “Does a user want to do session management or is he/she really not interested in that?” Because, like you said, Commands are “what a user wants to do”.

Fowler talks about using a helper …
He may talk about a View Helper, but your User Helper is not a View Helper. A View Helper is a class that contains logic that is really business logic but it’s business logic that is only required by a small number of Views, and implementing it into the business objects themselves would make them bloated, that is why they are in a separate class.

When using a Front Controller would you recommend only using the one page access point (eg .index.php)? Or would it make any sense to have a FrontController for each section of your site (eg. UserFrontController, NewsFrontController, etc)?
This depends on what you prefer. Like we’ve said before, if the switch statement grows too large, you can start using external files to determine which PageController must be loaded for which URL. But there is no reason why you can’t have multiple FrontControllers with switch statements in them.

Just a note though, it is possible to have multiple index.php files that all initiate the same FrontController class.

One solution would be modifying the FC to something like the following :


class FrontController 
{ 
    function get_controller($controller)
    {
        // untaint to protect against mallicious users
        $controller = strtr($controller, '\\/:*?"<>|', '_________');
        $filename = 'includes/controllers/' . $controller . '.controller.php';
        $classname = $controller . 'Controller';
        if (is_file($filename)) {
            include_once($filename);
            return new $classname();
        }
        // you might want to return a default controller instead
        trigger_error('no such controller : ' . $controller, E_USER_WARNING);
        return null;
    }
    function run() 
    { 
        $pageController =& $this->get_controller($_GET['page']);
        $pageController->execute(); 
        $view = $pageController->getView(); 
        $view->render(); 
    } 
}