Reputation: 10692
I have a simple CFC class that handles CRUD on a Product - Product.cfc.
I am extending the class to allow for additional properties based on the application - for instance CartProduct.cfc extends Product.cfc in order to allow for a Quantity property to be included.
In the Base Product.cfc class, I first pass in an ID, and use the ID in my read() method to retrieve the data from the database:
<cffunction name="read" returntype="Query">
<cfquery name="qData" datasource="mydb">
SELECT description
FROM mySKUTable
WHERE id = '#VARIABLES.Sku#'
</cfquery>
<cfreturn qData />
</cffunction>
<cffunction name="setSku" returntype="Product">
<cfargument name="Sku" type="String" required="true" />
<cfscript>
var qData = QueryNew("");
VARIABLES.Sku = ARGUMENTS.Sku;
qData = read();
VARIABLES.description = qData.description;
</cfscript>
</cffunction>
I want to extend this in CartProduct.cfc to retrieve and set the Quantity from a different table using the read() method:
<cffunction name="read" returntype="Query">
<cfquery name="qData" datasource="mydb">
SELECT quantity
FROM myCartTable
WHERE id = '#VARIABLES.Sku#'
</cfquery>
<cfreturn qData />
</cffunction>
<cffunction name="setSku" returntype="Product">
<cfargument name="Sku" type="String" required="true" />
<cfscript>
var qData = QueryNew("");
THIS = SUPER.setSku(Sku);
qData = read();
VARIABLES.quantity = qData.quantity;
</cfscript>
</cffunction>
When I do this, only the extended read() is called. This is fine, this is as designed. However, I'm looking for a way to have BOTH read() methods called, so I can first set the properties in the base class, and then set the Properties in the extended class.
Any thoughts on this?
p.s. I know I'm not using CFQUERYPARAM or validating my inputs, etc. I left that crap out in order to keep this simple, so please don't give me those suggestions right now.
Upvotes: 1
Views: 313
Reputation: 1046
You can use the "Super" scope to reference the extended component. So, to call the "read" method of Product.cfc from within CartProduct.cfc, call Super.read().
Upvotes: 0
Reputation: 10692
Ok, here's what I came up with:
Instead of returning a Query from the read() method, I'm converting the Query row to a Struct and returning the Struct. That way I can call SUPER.read() from within read() and then copy the the keys and values from the parent Struct into the new Struct at every level. It's a little more code, but it gets the job done.
<cffunction name="read" returntype="Struct" output="false">
<cfscript>
var _qData = QueryNew("");
var _properties = SUPER.read();
</cfscript>
<cfquery>
...
</cfquery>
<cfscript>
StructAppend(
_properties,
REQUEST.UDFLib.Query.queryRowToStruct(_qData)
);
return _properties;
</cfscript>
</cffunction>
Upvotes: 1