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 »", route="home")#</strong></p> | |
</cfoutput> |
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> |
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> |
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.