404 Error Handling in CFWheels

March 30, 2010 · Chris Peters

This is fairly simple, but I figured that I would share my approach for 404 error pages in CFWheels and see if anyone has a different/better way of doing it. This example demonstrates code used on cfwheels.org.

This is fairly simple, but I figured that I would share my approach for 404 error pages in CFWheels and see if anyone has a different/better way of doing it. This example demonstrates code used on cfwheels.org.

The Strategy

What I really wanted was a function that I could call whenever a given view’s record could not be found.

In my example case, I wanted to handle user IDs in the [CFWheels People Directory] that represent records that don’t exist. I had ended up removing user 31 (and a few others), so I wanted to display a helpful 404 error message every time http://cfwheels.org/user/profile/31 was accessed. (Note: the CFWheels People Directory doesn’t exist anymore.)

404 Error Page

So the first step was to create the 404 page itself, which I stored at views/main/error404.cfm.

<cfset layout.title = "Page Not Found | ColdFusion on Wheels">
<cfset layout.header1 = "Page Not Found">
<cfset layout.breadcrumbs = ["Page Not Found"]>
<!--- 404 error --->
<cfheader statuscode="404" statustext="Not Found">
<cfoutput>
<p>
We're sorry. We couldn't find the page that you're looking for. It has either been removed, or perhaps
you are accessing an inaccurate <abbr title="Uniform Resource Locator">URL</abbr>.
</p>
<h2><label for="search-query-404">Search</label></h2>
#startFormTag(controller="search", id="cse-search-box", method="get")#
<div>
<input type="hidden" name="cx" value="005724978648843866544:jpej79qhz14" />
<input type="hidden" name="cof" value="FORID:10" />
<input type="hidden" name="ie" value="UTF-8" />
<input id="search-query-404" type="text" name="q" />
<input type="submit" name="sa" value="Search" />
</div>
#endFormTag()#
<h2>Start from the Home Page</h2>
<p><strong>#linkTo(text="ColdFusion on Wheels Home &raquo;", route="home")#</strong></p>
</cfoutput>
view raw error404.cfm hosted with ❤ by GitHub

The real meat is the fact that I put the <cfheader> 404 reference in the view file. I look at anything that’s sent to the browser as a job for the view to handle, so that’s why I put the call there instead of in the controller file. In fact, because the page is fairly “dumb,” I didn’t put anything in the Main controller.

Rendering Helper

I also put a quick render404() function in the base controller at controllers/Controller.cfc so that I wouldn’t need to manually call renderPage(controller="main", action="error404") every time that I wanted to reference this new view. Your preference may be to not do this, but I’ll leave that up to you.

<cffunction name="render404" hint="Renders a 404 error page.">
<cfset renderPage(controller="main", action="error404")>
</cffunction>
view raw Controller.cfc hosted with ❤ by GitHub

Handling 404 Errors in the Controller

The last step involved actually using this functionality in the case that an invalid record ID was passed in the URL. So the user/profile action now looks like this:

<cffunction name="profile" hint="Displays user profile.">
<cfset user = model("customer").findByKey(params.key)>
<cfset loggedInUser = getLoggedInCustomer()>
<!--- If profile found, show it --->
<cfif IsObject(user)>
<cfset sites = user.sites(where="isApproved=1")>
<cfset plugins = user.plugins(where="isApproved=1")>
<!--- 404 error if not found --->
<cfelse>
<cfset render404()>
</cfif>
</cffunction>
view raw Users.cfc hosted with ❤ by GitHub

Fairly simple stuff. When loading the user object, I check to see if an object was returned. If not, then show the 404 page. Pretty reusable, and it only requires an additional if/else block in the controller to decide what to do.

Plus the file at events/onmissingtemplate.cfm can just use <cfhttp> to phone http://cfwheels.org/main/error404 in order to display the exact same error message during a more generic “template not found” scenario.

Besides identifying other places in the application to call render404(), that’s pretty much it.

About Chris Peters

With over 20 years of experience, I help plan, execute, and optimize digital experiences.

Leave a comment