To hopefully clear up some MVC confusion

(I’m putting this in a separate post to keep things organized a bit)

You wanted to see a FrontController + PageController + InterceptingFilters in action? Here goes:

class FrontController 
{ 
	function run() 
	{ 
		$filterChain = new SessionTrackingFilter(
			new AuthenticationFilter(
				new OutputBufferFilter
				(
					$this
				)
			)
		);
		
		$filterChain->processRequest();
	}
	
	function processRequest()
	{
		switch ($_GET['page']) 
		{ 
			case 'add': 
				$pageController = new UserAddController; 
				break; 
			
			case 'edit': 
				$pageController = new UserEditController; 
				break; 
			
			case 'list': 
				$pageController = new UserListController; 
				break; 
		} 
			
		$pageController->execute(); 
		$view = $pageController->getView(); 
		$view->render();
	}
}

Some explanation first before I show you the rest of the code. As you can see, in the FrontController, instead of directly selecting a PageController, now I set up a chain of InterceptingFilters and at the end of the chain I put the FrontController again. The request now gets processed by the SessionTrackingFilter, which passes it onto the AuthenticationFilter, to the OutputBufferFilter and finally back again to the FrontController.

Now for the intercepting filters:


class SessionTrackingFilter extends InterceptingFilter
{
	function __construct($nextFilter)
	{
		$this->nextFilter = $nextFilter;
	}
	
	function processRequest()
	{
		// do whatever needs to be done to start a session
		...
		
		// let all the other filters do their work
		$this->nextFilter->processRequest();
		
		// and after those filters have done their work, close the session
		...
	}
}

class authenticationFilter extends InterceptingFilter
{
	function processRequest()
	{
			if ($validCookieFound)
			{
				// the user has been authenticated, so move on to the next filter
				$this->nextFilter->processRequest();
			}
			else
			{
				// whoah, hold up, we need to ask the user for authentication first
				
				echo 'Please enter your username and password in the form here etc. ';
				
				// now we do not move on to the next filter, we stop processing the request here
				// and return control to the previous filter in the chain
				return;
			}
		}
	}
}

class OutputBufferFilter extends InterceptingFilter
{
	function processRequest()
	{
		ob_start();
		
		$this->nextFilter->processRequest();
		
		ob_end_flush();		
	}	
}

As you can see, the InterceptingFilters are clean and small classes. If for some section of your website you need a different authorization method, or perhaps you don’t want to use sessions, you simply rearrange the chain of filters: reuse them.

That is the most important advantage I can think of, and it is an advantage that comes from good object oriented design: reusability. You can reuse the filters and rearrange them in any order, something you can’t do when you implement their behaviour in a base PageController class (you would theoretically need one for every possible combination of filters in any order).

For more information about InterceptingFilters, I can also recommend the link seratonin gave: http://www.corej2eepatterns.com/Patterns2ndEd/InterceptingFilter.htm You’ll see that the example I gave above is not so much different from the Java code.

Also

One solution would be modifying the FC to something like the following + code
That’s what McGruff said :slight_smile:

That’s what McGruff said

Yeah, you’re right - i kind of missed that. But i still think my example is bit “cleaner” (if that somehow justifies my posting :wink: )
I have in my own framework i distinction between something called actions, and actual pagecontrollers. The actions are commands that gets invoked directly by the frontcontroller (somewhat like McGruff’s example. It could be for instance an action called “logout” … in general they handle forms. Actions always redirect to either a pagecontroller or another action.
Pagecontrollers on the other hand may do some updating logic, but their main concern is to render views.

Thanks for the nice clean example with explanation. I can see exactly what you mean now, by the flexibility of your design.

I can see myself using a hybrid solution like I described in my last post. A base Front Controller, with the InterceptingFilters and any global operations I need to do (most of which I can see being done in the InterceptingFilters). Then I could extend that base FrontController to use it with each section of my site (eg, User, News, Orders), where I would basically just override the run() function with a custom switch statement for the PageControllers in each section. Does this make sense or am I just creating a lot of extra work and overhead by doing it this way?

Just one more question, is there any type of significant performance/overhead issues between FrontControllers and PageController implementations?

Thanks again all,

Peer

You wanted to see a FrontController + PageController + InterceptingFilters in action? Here goes:

and now, if you change the code of function processRequest from FrontController to:

function processRequest() 
    { 
        $pageController =& pageControllerFactory::getPageController($_GET['page']); 
             
        $pageController->execute(); 
        $view = $pageController->getView(); 
        $view->render(); 
    } 
class pageControllerFactory 
{ 
    function getPageController($pc) 
    { 
        $filename = 'includes/controllers/' . $pc . '.controller.php'; 
        $classname = $pc . 'Controller'; 
        include_once($filename); 
        return new $classname(); 
    } 
} 

naturally you shall make some validations somewhere, but it eliminates the need for a switch statement


...
function processRequest() 
    { 
        $pageController =& pageControllerFactory::getPageController($_GET['page']); 
              
        $pageController->execute(); 
        $view = $pageController->getView(); 
        $view->render(); 
    } 
...

This is cool, I like the idea actually :slight_smile:

And I’m assuming you can still use the Intercepting Filters as before without any changes to them huh ?

Thanks a lot for the example :slight_smile:

Earlier in the thread Captain Proton posted this

Thanks to the latest example that have been provided I really see what it meant. However, I do have another question, where does one setup which filters should be run? In the quote above, different scenarios are laid out where different filters would need to run depending on the page/section requirements. How are you configuring what should be in the FilterChain?

The example InterceptingFilter has already paid off dividends in the progress of my project, thank you very much.

Peer

I dont know the term “View Helper” but I wouldnt put business logic in a class that specificly relates to the view. I dont see why a business object shouldnt have bussiness logic. Putting business logic in a view object is not a good answer IMO. View objects should only have presentation logic if any.

Whether or not you should use a Helper like below in php is a different discussion, I was only offering a solution for otnemem.

To exactly quote his example from PoEAA pg 355-357:

class Artist {
  private $name;
  private $albums = array();
  public function getName() {
    return $this->name;
  }
  public function getAlbums() {
    return $this->albums;
  }
}
class ArtistHelper {
  private $artist;
  public function ArtistHelper(Artist $artist) {
    $this->artist = $artist;
  }
  public function getName() {
    return $this->artist->getName();
  }
  public function getAlbums() {
    return $this->artist->getAlbums();
  }
  public function getAlblumList() {
    $result = '<ul>';
	foreach($this->getAlbumns() as $album) {
	  $result = '<li>' . $album->getTitle() . '</li>';
	}
	return $result . '</ul>';
  }
}
$artist = Artist::findNamed($request->getParameter('name'));
if ($artist == null) {
    // foward to Missing artist error
} else {
    // Below is a jsp/servlet thing.
	// but is passing the artist to the
	// view via a helper
    $request->setAttribute('helper', new ArtistHelper($artist));
}

By chaining I meant more like a pipe and filter or intercepting filter (poor choice of wording) type architecture. Which would be something that happens internally when the Front Controller is carrying out a request. Although, you could definitely chain together two use cases. If you have a use case like Update News and you want to immediately forward control to View News upon success, I could see something like that happening. I am using use cases/features to help me partition my application. If View News is a use case what has to happen behind the scenes to provide that functionality is a completely different story. It may include authentication, authorization, logging, but that is all behind the scenes. What the user sees and cares about is viewing the news. So there is what the user observes is happening and what is happening internally.

JT

I dont know the term “View Helper” but I wouldnt put business logic in a class that specificly relates to the view. I dont see why a business object shouldnt have bussiness logic. Putting business logic in a view object is not a good answer IMO
If you read what I said precisely, you’ll see that I did not say that a business object should not have business logic. That wouldn’t make sense of course. What I said is that some business logic might only be required by a very small number of views and if you have to add all of this business logic to the business objects themselves, they would become very bloated objects with dozens of methods.

To exactly quote his example from PoEAA pg 355-357:
I wasn’t aware the book contained PHP code examples as well… ? …

Youre right. The point is that a Helper Object will restrict the use of domain logic in the view.

:slight_smile: You caught me. I added dollars signs and a foreach instead of an iterator.

The only additional “burden” imposed by a FrontController is the webserver functionality. In a pure PageController setup, apache (or etc) carries out this task instead saving on a small chunk of code. However, if a FC selects PCs by dynamically including files, any losses are more theoretical than real. Lengthy switch cases or other methods such as xml files might be another matter.

Apart from that, FC and FC-less designs all have to do exactly the same thing (with the same amount of code) namely carry out a series of tasks in response to an http request.

There is, as far as I can see, no strong argument to use one design over the other - your choice. Harry Fuecks, on phppatterns.com, does make the point that FC-less designs may make it easier to integrate different apps.

Using intercepting filters to carry out non-client tasks has never felt quite right to me. I think it arbitrarily over-emphasises client output in the design - just one of a series of actions. Why pluck the client page out of the filter chain? And, if not this, why do the rest like that? I know a lot of people like to conceptualise things this way - just my opinion.

While I don’t fully agree with making everything under the sun a object, there is a better way and more expandable way to do this instead of using a switch statement, the following gets rid of ever having to edit your core code to expand. It does add a certain limitation though on class names.


    if($_REQUEST['page']) {
          $method = 'User'.$_REQUEST['page'].'controller';
          if(class_exists($method)) {
   	$pageController = New $method;
          }
    }
   

Just wanted to add… This assumes you already loaded all your librarys from the beginning, so theres no need to do live “taint” and includes based off the REQUEST making things more secure…

Taint checking is fine and all but you should only use it if you have no choice… Imaging what would happen to half the php programs that rely so much on includes and taint checking if some bug is found in what ever function you use to taint check that allows something to slip by.

Alright, Captain Proton, I have another question for you about the Intercepting filters. In another thread (http://www.sitepoint.com/forums/showthread.php?t=157003) you said this

You don’t. InterceptingFilter is an application of the (more general) Chain of Responsibility pattern. Key to this pattern is that each object in the chain can either handle the request or pass it on to the next object in the chain (the target), without knowing what specific object that target is.[/QUOTE]
In your earlier example the Front Controller is the last item in the filter chain and the location where the page controller is initialized. Also, the Authorization filter example stops the chain if authorization fails and therefore it never reaches the Front Controller and a Page Controller is never selected… and I’m sure you can see where this is going.

So, if the Intercepting Controller is not supposed to notify anything else in the chain as to what happened, how do I tell my Front Controller that authorization failed and it needs to load the AuthorizationFailedController?

(geez, this thread is making me thing far too hard for a Friday!)

Peer

how do I tell my Front Controller that authorization failed and it needs to load the AuthorizationFailedController?

Not sure, though untested, I was thinking that you put a variable in $_REQUEST, and the next filter up would check for this ?

On the other hand, has anyone implemented an Observer with an Front Controller/Intercepting Filter, say to moniter the status of each filter ?

You wouldnt want to include all of your libraries on each request. This will cause alot of unnessesary overhead.

A front controller at a minimum needs to have a default page to show if no $_REQUEST[‘page’] param is given. It also needs to be able to tell the difference between a valid $_REQUEST[‘page’] and non-valid one, creating the PageController on a valid and sending a 404 or creating the 404PageController on a non valid request.

Heres the example Ive used before:

class FrontController {
    var $defaultPageController;
    var $requestPageParam;
    var $pageControllers = array();

    function FrontController($defaultPageController, $requestPageParam = 'page') {
        $this->defaultPageController = $defaultPageController;
        $this->requestPageParam = $requestPageParam;
    } 

    function &getPageController() {
        $pageControllerName = $this->getPageControllerName();
        return $this->getPageControllerInstance($pageControllerName);
    } 

    function addPage($name, $className) {
        $this->pageControllers[$name] = $className;
    } 

    function getPageControllerName() {
        if (!array_key_exists($this->requestPageParam, $_GET)) {
            return $this->defaultPageController;
        } 
        return $_GET[$this->requestPageParam];
    } 

    function &getPageControllerInstance($pageControllerName) {
        if (!array_key_exists($pageControllerName, $this->pageControllers)) {
            header("HTTP/1.0 404 Not Found");
            die();
			// Do the above or the below.
            require_once './controller/Error404PageController.php';
            return new Error404PageController();
        } 
        require_once './controller/' . $this->pageControllers[$pageControllerName] . '.php';
        return new $this->pageControllers[$pageControllerName]();
    } 
} 
$fc = new FrontController('index');
$fc->addPage('index', 'IndexController');
$fc->addPage('admin', 'AdminController');
$pc =& $fc->getPageController();
// Below could be moved into the FrontController
$pc->execute();
// Below could be moved into the PageController
$view =& $pc->getView();
$view->render();

What I provided was just the very basic of examples.

It depends on how large your site is. You could also php5’s overload system but then you have to do taint checking, The whole 404 and defaults are simple to add in.


  if($_REQUEST['page') {
  	$method = 'User'.$_REQUEST['page'].'controller';
  	if(!class_exists($methd)) {	
  	    $method = 'User404controller';
  	}
  } else {
  	$method = 'UserHomecontroller';
  }
  $pageController = New $method;
  

Quick and simple… Doesnt require editing the code to add a new controller.

If you want to limit loading to just a single library, You can use php5 autoload… The great thing about that, by using autoload you are auto filtering the request php will not let you create a class with any char’s someone might use to inject attack your system.

Controllers are nice and all but you have to look at what your ultimate goal is.
If your developering for yourself or a internal project thats fine but if your developing for the public you have to assume the person installing your code may not know php, The idea of editing a core file of the system could very well turn them away from ever using your product.

Well done. I only made comment because of the use of $_REQUEST like this. For someone who didnt know better they may take this example and use it in a more dangerous way by getting rid of the string contatenation.

If youre using something like this you need to be careful of the way youre files / directories / classes are named.

Excellent post Captain Proton. You are now the author of an important and featured thread
Thanks, I’m honored! :slight_smile:

The base InterceptingFilter class would contain a constructor that accepts a ‘target’ filter, the $nextFilter in the examples above. It also has a processRequest() method that does nothing but call the $nextFilter’s processRequest() method: in other words, it passes on the request to the next filter in the chain.

In the quote above, different scenarios are laid out where different filters would need to run depending on the page/section requirements. How are you configuring what should be in the FilterChain?
If you have multiple sections of your website/application that need a different series of filters, the easiest way is to simply have more than one FrontController and let each one set up its own filter chain.

I dont know the term “View Helper” but I wouldnt put business logic in a class that specificly relates to the view
The guys at sun would :slight_smile: [url=http://java.sun.com/blueprints/corej2eepatterns/Patterns/ViewHelper.html

Though if I do remember, after reading the book several times, M Fowler does talk about a helper and it isn’t the View Helper Pattern either
My apologies to you and to Brenden Vickery. You are right, I have mixed up a J2EE pattern with Martin Fowler’s book.

Using intercepting filters to carry out non-client tasks has never felt quite right to me. I think it arbitrarily over-emphasises client output in the design - just one of a series of actions.
I think that Intercepting Filters help you to view the clear distinction between a) the code that do the actual work for the task that a user wants to accomplish (the PageControllers) from b) those that carry out the ‘boring’ and distracting-from-the-main-concern stuff (the InterceptingFilters). But I have grown used to have my code structured like that so can’t say that I’m totally unbiased.

In your earlier example the Front Controller is the last item in the filter chain and the location where the page controller is initialized. Also, the Authorization filter example stops the chain if authorization fails and therefore it never reaches the Front Controller and a Page Controller is never selected… and I’m sure you can see where this is going.

So, if the Intercepting Controller is not supposed to notify anything else in the chain as to what happened, how do I tell my Front Controller that authorization failed and it needs to load the AuthorizationFailedController?
Very good question :slight_smile: That’s the great thing about Intercepting Filters. They have the power to ‘intercept’ the request and do something else with it. In the case of authentication, the AuthenticationFilter can stop the request from being processed by the PageController by simply not passing it on to the next filter in the chain. Here is the code from my AuthenticationFilter base class. It’s the “skeleton logic” for authentication, where subclasses can fill in the “rest of the body” so to speak.

function processRequest(HTTPRequest $request, HTTPResponse $response)
{
	if ($this->containsAuthenticationCredentials($request))
	{
		$this->nextFilter->processRequest($request, $response);
	}
	else
	{
		$pageController = $this->getAuthenticationPageController($request, $response);
		$pageController->execute();
		$view = $pageController->getView();
		$view->render();
	}
}

I think the code is kind of self explaning, but feel free to ask questions of course is anything is not clear.

Thanks for the example (again :)). I think I was looking at the filters a little to literally. Some of the explanations I had read seemed to indicate that the InterceptingFilter either wasn’t ‘allowed’ or ‘supposed’ to take control of specifying the PageController. I figured it could, but it didn’t seem like ‘good design’.

Out of curiosity, I notice you have two arguments in your processRequest function. The request var is pretty self -explanatory, but what type of information is usually passed in the $response argument?

Thanks

Peer