Application Controllers

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Application Controllers

Post by nielsene »

I've been reading PoEAA and SitePoint and a few other resources trying to get a better handle on Application Controllers. It seems to be that they are most useful in a multi-page form/wizzard environment; however I do see a lot of places where they use a single Application Controller (dispatched to by a Front Controller). I think I can understand that seeminly redundant setup when an application is growing, but I wouldn't expect it to hold for long?

Am I right to assume that I'll end up with one AC for each wizzard, and a few others for generally cohesive, but not-really wizzard like, "modules" of the application? (For instance a purely view/retrieve/select style series of pages that slice into data along different axes, all cross-linked)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

I've always felt that Fowler was a little vague on controllers. Reading between the lines a little bit, here's what I understand he's saying.

He mentions Page Controllers, Front Controllers and Application Controllers. Front/Page are input controllers ie they receive input and then decide what to do with it. The "decide what to do" with the request bit is the application controller logic. If you draw a line around the input-receiving code in a PageController you're left with an ApplicationController. Pretty much the same thing in a FrontController except that the FrontController also has the task of identifying the request type.

The wizzard example for the ApplicationController is good as an illustration of how the same request type can lead to different responses but I feel that it tends to push people towards viewing ApplicationController as a kind of specialist tool. If a single request type can lead to more than one possible response, some application controller logic is required and this is the case for virtually all dynamic web pages. For example, a request for a restricted page might lead you to a login page if you're not logged in. There will likely be several possible error pages: perhaps a db connection couldn't be made, or a forum topic has been deleted, or the request had bad syntax, for example. Apart from really trivial cases like echo phpinfo(), I'd see application controller logic pretty much everywhere.

The code might be mixed in with a PageController or FrontController, or it might be implemented in a dedicated class - or classes. You could write ApplicationControllers for different requests or, with something like ChainOfResponsibility, you can have a single application controller framework which can be configured for different types of request.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

I was thinking that the access-denied, please log-in style of "decision" while handling a request would still be part of the Front Controller's responsibility -- one of the early handlers would catch that. And that handler for most dynamic pages could just be dispatched to directly from the FC. However for views that are more sequenced, the AC would be appropriate -- something that wraps a UoW or similar to help keep the work-flow organized.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

I'm still a little confused here.

Let me attempt to out-line the flow of control through the "tasks" required to generate a response and then I'll attempt to outline where I think the various controllers/patterns fit in. (I'm attempting to keep the initial "tasks" somewhat vague so that either Front/Page controllers can follow in the pattern discussion)

1. Apache Gets Request and invoked PHPs
2. Something decides what "script" to start
3. Something packages up the passed parameters
4. Something decides on the appropriate actions given the passed parameters and the requested script
5. Some action is preformed
6. Something seleccts what response to generate
7. Response sent to the browser

In a non-pattern, "standard script" implementationn this would be
1-3: Apache/filesystem/php superglobals
4-7: the requested script

In a Page Controller based design:
1-2: Apache/File System
3: Page Controller creates a RequestGateway (HttpRequest)
4. Some sort of chain of Handlers attempt to "claim" the task
5,6. "Winning handler" preforms its action and selects a response
7. Template View/Transform View

In a Front Controller based design:
1. Apache
2. Front Controller (sometimes called Dispatcher?)
3. Front Controller creates a RequestGateway (possibly/usually using the decision of the Dispatcher aspect)
4-7 same as the Page Controller



Is this what you're also saying? If this is the case it would seem to be more clear to talk about whether the application implements a Dispatcher (overriding the webserver) instead of Front versus Page? The other useful axis it seems is "isolated" versus "modulle" (Roughly Page versus Application Controllers, but trying to avoid those terms at this point)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

nielsene wrote:I was thinking that the access-denied, please log-in style of "decision" while handling a request would still be part of the Front Controller's responsibility -- one of the early handlers would catch that. And that handler for most dynamic pages could just be dispatched to directly from the FC. However for views that are more sequenced, the AC would be appropriate -- something that wraps a UoW or similar to help keep the work-flow organized.
It's often done like that, with InterceptingFilter. Personally I think InterceptingFilter is evil. As it's commonly described, it mixes up too many different kinds of pre and post processing tasks: input filters, authentication/authorisation, logging - everything including the kitchen sink. Some filter. Some intercept. Some don't do either. A magic quotes filter silently filters values - what you might intuively think of as "filtering". However, in InterceptingFilter filters might also carry out "logical" filtering, intercepting the program flow (application controller logic). An authentication filter might make a decision on whether to continue processing the request or to stop and show a login page. Another filter example, logging, doesn't filter in any sense of the word.

InterceptingFilter does seem to be popular though.

One of the reasons for the ChainOfResponsibility design is to highlight application controller logic, splitting it off from the rest. If application controller logic simply changes the program flow based on the state of something or other, I don't see any difference the wizard case and other decisions such as failed authentication, or an unavailable db host.
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

nielsene wrote:Let me attempt to out-line the flow of control...
...
...
Is this what you're also saying? If this is the case it would seem to be more clear to talk about whether the application implements a Dispatcher (overriding the webserver) instead of Front versus Page? The other useful axis it seems is "isolated" versus "modulle" (Roughly Page versus Application Controllers, but trying to avoid those terms at this point)
Yes, that's the way I look at it.

I'm not always sure what people refer to with "dispatching": the FrontController/webserver routing or a PageController decision - or both? I prefer to talk about Front/Page Controllers.

I guess at the heart of all these semantics are various decisions:
- what request type is this (viewforum, edit profile, etc)?
- which of out a range of possible responses associated with the request type should be made?
- any further decisions within the response such as whether to show a happy birthday message, send some kind of email, etc
User avatar
Buddha443556
Forum Regular
Posts: 873
Joined: Fri Mar 19, 2004 1:51 pm

Post by Buddha443556 »

nielsene wrote:In a non-pattern, "standard script" implementationn this would be
1-3: Apache/filesystem/php superglobals
4-7: the requested script
Wouldn't you usually have at least a simple page controller for GET/POST?
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

Buddha443556 wrote:
nielsene wrote:In a non-pattern, "standard script" implementationn this would be
1-3: Apache/filesystem/php superglobals
4-7: the requested script
Wouldn't you usually have at least a simple page controller for GET/POST?
I don't think so. That example was trying to show the way most non-pattern aware/non-OOP developers structure their code. In part to give a baseline for other people to see what we're talking about. Most scripts I've seen just fetch directly from POST/GET and then (hopefully) sanitize/validate the input.
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

With the mod_rewrite / forcetype of mod_mime / auto_prepend and auto_append php.ini directives one can implement a really powerful frontcontroller and actionmapper (without the need to map everything through the same file / url). With include / require and http Location header actionforwards can be realised.


And the best of all this is that you can have an implementation that has all these patterns without forcing you to use oop (although, i think oop can make the dispatching/executing and handling chains easier)
stryderjzw
Forum Newbie
Posts: 21
Joined: Sat Aug 06, 2005 5:45 pm

Post by stryderjzw »

Hello.
nielsene wrote: In a Page Controller based design:
1-2: Apache/File System
3: Page Controller creates a RequestGateway (HttpRequest)
4. Some sort of chain of Handlers attempt to "claim" the task
5,6. "Winning handler" preforms its action and selects a response
7. Template View/Transform View
This is something I'm trying to achieve. I like Page Controllers as opposed to Front Controllers...

I also read posts by McGruff about Chain of Responsibility, claiming a handler. I believe there was sth like this posted somewhere:

verify request/ 400 handler
"database online?" handler
authentication handler
authorization handler
"active handler"
404 handler

The Chain would run through and decide which one to claim and run. Does anyone see any trouble using a Chain of Responsibility with a Page Controller?

But I have a question. What if this "active handler" doesn't require authentication and authorization? What if only certain actions of my app require authentication? My thought is that every "handler" would know if authentication is required for itself, so all information about the handler is self-contained in each handler. Does this sound like a good idea?

Then, does the "authentication" handler need to read the "active handler" to know what to do... Hmm, hard to explain my thoughts :(


I hope people understand what I mean. Please share your experience and insight. Thanks! :)
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

I don't see any problem with a CoR with a Page Controller. I think it means you'll end up with the top of each page-script looking like

Code: Select all

$pc = new PageController();
$pc->addHandler(new VerifyRequestHandler());
$pc->addHandler(new DatabaseDownHandler());
//...
$pc->invoke();
So its a little unlike the "simple" page controller mentioned in PoEAA, as I think the simplest version just places the "active handler" into the contents of the page. The CoR version would make it easy to change your mind and convert to a FrontController later if you want -- normally that's a tough refactoring... this way you keep your options open.

You might want to think about if you want to define the "active handler" in the same file as the current script: ie

Code: Select all

class SomeScriptHandler()
{
}
class VerifySomeScriptHandler()
{
}
$pc = new PageController();
$pc->addHandler(new VerifyRequestHandler());
$pc->addHandler(new DatabaseDownHandler());
//...
$pc->invoke();
If you want to try to keep the logic for a given script close to it. I think in large applications this would be bad, but for smaller ones it might be an interesting way to keep the "simplicity" of a Page Controller, but the benefits of a CoR, with the fexibility of changing to a FC if the application requires it later. That said, I don't think I'd do it :)

In regards to your later question, I would assume that the "active" handler or the active view, could still query the Request/Context for optional authentication/authorization information. The earlier Authentication/Authorization handlers are to catch acccess-denied type issuess not handle the slightly different, but related actions for the different levels of permitted access. (Am I making any sense?)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

stryderjzw wrote:But I have a question. What if this "active handler" doesn't require authentication and authorization? What if only certain actions of my app require authentication? My thought is that every "handler" would know if authentication is required for itself, so all information about the handler is self-contained in each handler. Does this sound like a good idea?
Basically it's dealt with by chain configuration. If the active handler doesn't require authentication, you simply don't add this handler to the chain.

With a CoR, individual handlers can become simpler and clearer with different responsibilities pushed into separate classes. Handlers which require authentication just assume it's already been dealt with; they don't contain any authentication code and so they end up more focussed on a single responsibility. In general, CoR works well in situations where you can identify loosely coupled objects.

When I'm talking about handlers I'm assuming that each handler corresponds to a browser page ie failed authentication leads to a login page or failed authorisation leads to an "access denied" page. If for example, authorisation simply decides which elements appear on the page there would be no separate authorisation handler for this request type.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Having gone through an extensive discussion about Application Controllers recently I think one of the main things missing from this discussion is that Application Controllers usually contain or are a State Machine. It is this quality of them that allows them to handle everything from complex wizards to simple form processors possible. There seems to be a choice in State Machines between binary tree based vs. state/transition based.

The details are daunting with all of the controllers that Fowler covers. And they get more complex the more of your application code they are in contact with. Front Controllers are pretty straightforward to build because they just dispatch other controllers. But the Input and Application Controllers quickly become very complex and force a myriad of decisions, expecially about how common code and services are accessed. I'd be interested to hear the experiences of anyone else has tried to implement these beasts.

PS - Fowler refers to research done by Dai & Knight and their articles will fill you brain with tons of gunk about these controllers
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

Thanks arborint that does help to add a little to my internal vision of an Application Controller and I can think of a few places in my legacy application where it'd be the right thing to use. (Actually looking forward to playing with a state machine on two of my very long wizzards where its common be be able to skip many steps in certain situations.)

I'm still battling my way through adding a Front Controller system to my legacy application, with fall back to the old pure script/page controller system. I'm getting close and I'll definitely post what I come up with when its done.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Starting with a Front Controller is the best way to go. Doing that by definition makes you modularize your actions using the Command pattern. Typically at first those Commands are just Transaction Scripts, which is ok for many things. But as you start seeing a lot of code duplication between actions then having your actions inherit some kind of base controller makes sense.
Post Reply