CFWheels – Don’t forget your filter

One of the features of CFWheels which I’ve been guilty of ignoring in the past is the combination ‘filter’ and init().

In your controller model, you have two really powerful tools at your disposal. The init() function, which runs before each request to the controller, can allow you to do lots of preprocessing logic, and make sure everything is ‘good to go’ with displaying your view. The filter function, when combined with init(), means you can call specific functions for a view, and keep any recurring code out of the view function itself.

I often have caught myself doing this multiple times in a controller (in this case, users.cfc)

<!---View User--->
<cffunction name="view">
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
</cffunction>

<!---Edit User--->
<cffunction name="edit">
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
</cffunction>

etc.

All I want is the current Users data, and often I’d want it for the view, list, edit functions etc. If you find that you’re repeating code in wheels, stop and ask your self whether there’s a better way.

Using the init function and filter, we can replace each call by simply writing the function once, and popping the call to the function in the filter. So:

<!--- init --->
<cffunction name="init">
<!---Filters--->
<cfset filters(through="getCurrentUser", only="view,edit")> 
</cffunction>

<!--- My new private function --->
<cffunction name="getCurrentUser" access="private">
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
</cffunction>

This means our object of currentuser is now available to the view and edit functions. We could also add some checks to see whether the session is valid, the object is returned, etc. Your resulting function might look something like this:

<cffunction name="getCurrentUser" access="private">
<cfif structkeyexists(session.currentuser, 'email')>
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
<cfif NOT isObject(currentuser)>
<cfset userError()>
</cfif>
<cfelse>
<cfset userError()>
</cfif>
</cffunction>

<!---An additional private function to throw a user related error--->
<cffunction name="userError" access="private">
<cfset flashInsert(error="User Not Found")>
<cfset redirectTo(back=true)>
</cffunction>

Once you get your head round this relatively simple principle, it makes creating your controllers very quick indeed..!