CFWheels Calculated Properties on Steroids using an afterFind Callback

One limitation with using calculated properties in your CFWheels models is that one is limited to what can be achieved using SQL. CFML has almost infinite possibilities for formatting strings which simply cannot be done easily (or at all) in SQL.

A technique that I use to get around this limitation is to create new properties using an afterFind callback for both objects AND queries in a single callback.

In the code below I create two new properties, createdAtShort and createdAtLong which are just different date masks applied to the trusty createdat property. It’s a fairly simple example, but highlights the huge potential of keeping this type of logic in your model and out of your views. Hopefully this will get your brain moist.

<!--- /models/User.cfc --->

<cfcomponent extends="Model" output="false">

  <cffunction name="init">
    <cfset afterFind("$$setStuffAfterFind")>
  </cffunction>

  <cffunction name="$$setStuffAfterFind" access="private">
    <cfif StructKeyExists(arguments, "createdAt")>
      <cfset arguments.createdAtShort = DateFormat(arguments.createdAt, "d/m/yy")>
      <cfset arguments.createdAtLong = DateFormat(arguments.createdAt, "dddd, dd mmmm yyyy") & " " & TimeFormat(arguments.createdAt, "hh:mmtt")>
      <cfreturn arguments>
    </cfif>
  </cffunction>

</cfcomponent>

Now you can call your model and the result should contain your new properties..

<!--- /controllers/Users.cfc --->

<cfset user = model("User").findOne()>
<cfset users = model("User").findAll(maxrows=5)>

<cfdump var="#user.properties()#">
<cfdump var="#users#">

Notes:

  1. Avoid performing further database operations inside the callback when using findAll.. y’know the whole querying within a recordset loop thing..
  2. afterFind callbacks are not called on included models. So.. model("Company").findAll(include="Users") won’t contain your new properties.

UPDATE: Chris Peters has since shown me the error of my ways.. it turns out that the arguments scope can be used for both queries and objects. This has simplified the entire concept considerably (and made ‘my’ code look eerily similar to the official CFWheels docs! The code and description above have been modified to use arguments scope.

Leave a comment