Page Controllers: One Year Later

Just over a year ago, I started using Page Controllers. I blogged about the experience in the first weeks, but since then have let the topic slide. After a year of using them, it seems like a good time to report on my opinion with the benefit of experience.

The quick answer is that I still like Page Controllers - indeed more so than I did a year ago.

I have discovered for many pages I have a fair amount of page-specific logic. This might be getting a recordset from a component or setting some simple variables for the page. Historically, I have put all of this logic on top of the file (or, perhaps, in an included file) above the output for the page. This was effective in keeping my code organized but for complicated page could result in a significant amount of logic code above the display code.

This result felt clumsy and ugly. More to the point, however, the code got in the way if I needed to have an HTML author make a minor change to the page. It was hard to give clear direction on what they could or could not change (usually I put a comment in the code to mark the beginning of output and told them not to edit anything above that comment). What I really wanted was some way to hide the logical code from an HTML programmer (even if that HTML programmer was me).

So, for sample-page.cfm I would have the following code at the top of the page instead of any of the normal logic:

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

The "loadData" method of the controller (which should probably have a better name) would build up and return a structure of data. The StructAppend() line above then adds that data to the variables-scoped data for the page.

Inside that component, I can require or param a variable in a way that I have found to be more effective than what I had done before.

To require a variable, I use the "require" method of the PageController.cfc that my page controller extends. So, to require "URL.id" I might use the following code:

<cfset require("URL.id","integer","mypage.cfm")>

Then if URL.id doesn't exist or isn't an integer, then the browser will be redirected to mypage.cfm.

If I want to provide a default for URL.id instead, I can use the following code:

<cfset param("URL.id","integer",0)>

This would set URL.id to zero if it isn't defined and an integer. Incidentally, it also defines an integer as being less than or equal to (2^31) which will prevent the problem some sites may have seen with very high values being passed in the URL.

I have been really happy with my decision to use Page Controllers and have yet to have a moment's pause about my decision (so far).

Related Blog Entries

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Do you have a controller for every page or just the pages that have the need for more complicated logic?
# Posted By Jason Holden | 3/26/08 8:16 AM
Jason,

Great question!

The answer really deserves its own entry, but the simple answer is that I only have a Page Controller where I feel one is needed.
# Posted By Steve Bryant | 3/26/08 8:34 AM
After using your page controller model I'm starting to see the value in them.
# Posted By Jason Holden | 4/7/08 7:04 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.