A ColdFusion Page Controller

A hate to admit it, but ever since I stopped using Fusebox a few years ago, I have been without a controller. I had my view separated from my model, but no controller to be seen. In fact, I even questioned the need for a controller on most of my projects (while seeing how it could help on larger projects). I was all ready to write a "Do I need a Controller" blog entry.

And then...

I discovered the Page Controller.

Most ColdFusion frameworks - at least the so-called MVC frameworks - are really Front Controllers. That is, they handle incoming requests and coordinate processing among multiple requests. Per Martin Fowler, a Front Controller is "A controller that handles all requests for a Web site."

A Page Controller is "An object that handles a request for a specific page or action on a Web site." (again, per Fowler).

My implementation of a page controller starts with a PageController.cfc that can be extended by each page controller. This has following methods that can be used by any page controller:

  • go (basically just cflocation)
  • param (similar to cfparam, but default kicks in instead of error for incorrect data type)
  • require (similar to cfparam, but no default or error - uses redirect for not defined or wrong data type)

The page controller itself is integrally tied to a given page. Therefore, I name it the same as the page (except the extension) and put it in the same folder). So, "about.cfm" would have a page controller called "about.cfc" (noting that this would only be for pages that need a page controller).

My view files have access to shared-scope variables (such as Application scope) and can do output, but don't perform any business logic or run any queries. My model components don't have access to shared-scope variables and can't do output, but can perform business logic and run queries. I think this is standard in both cases.

My page controller can acess shared-scope variables, but only in the pseudo-constructor. They cannot do output or perform business logic. Instead, they get data from the model and send data from the view to the model. The advantage of a page controller is that while a method of the model cannot know about the structure of a form in the view, the page controller can. This allows it to translate the form structure of a page to the API of a model method.

Here is an example of the top of a view page ("sample-page.cfm") that is using a page controller:

<cfset Controller = CreateObject("component","sample-page")>
<cfset StructAppend(variables,Controller.loadData())>

The load loadData() method returns a structure of variables that should be available to the page. You can take a look at the example sample-page.cfc to see what the page controller itself could look like.

The page controller can also have methods to respond to form posts. These methods can then translate the form structure into data appropriate for the API of one or more methods in the model. The saveQuiz() method in sample-page.cfc is an example of this. You can see how passing in the Form structure to a method in the model wouldn't have worked here, but the code to do the translation doesn't really fit in a view file either.

I often make these methods access="remote". This allows me to submit a form directly to the controller (though I have yet to do so). This seems to open up a security issue, but as anyone could post any form to your page anyway, it really just makes clear the entry-point for external data that already exists.

Although I don't have time to cover it in this post, this use of a page controller also makes AJAX much easier (hopefully I can cover that in a post next week).

My one warning about my use of page controllers is that I have only been using them for a few weeks. So, I haven't run into any trouble with them, but nor have I used them for very long.

Related Blog Entries

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
So -- its' been about a year. Have page controllers been working out for you?
# Posted By Tony Garcia | 3/18/08 11:07 AM
Great!

It has actually been a year since I originally wrote this post so it is definitely time for a follow-up post. I will try to get that done soon.

In the meantime, I will say this:

I love page controllers! I still use them basically as I described in this entry. As I glance at the description now, I see that I should have explained it better which I will try to do soon.

The only thing that I have changed is that I use onMissingMethod on CF8 to create a sort-of dual inheritance for labor saving. I will try to cover that soon as well.
# Posted By Steve Bryant | 3/18/08 11:26 AM
Cool. While I do like the Coldbox front controller framework, I think it can be overkill for less complex projects and I'm kind of "shopping around" for a good methodology for those projects that will stay in the spirit of MVC. I've heard of page controllers before and when I did a search on page controllers in CF, your blog post came up. I'm looking forward your followup as well as hearing about your onmissingmethod technique.
# Posted By Tony Garcia | 3/18/08 1:28 PM
Hi,
I have posted a simple example on onMissingmethod here.

http://cf-examples.net/index.cfm/2008/8/25/onMissi...
# Posted By Ahamad | 8/25/08 7:51 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.