Search code examples
coldfusioncoldfusion-2018

Why can't I instantiate a CFC's method using New


I am trying to instantiate a CFC using this simple syntax

<cfset Sale = New pathtocfcfolder.sale.GetSale(SaleID = URL.id) />

When I run the above I get an error saying

Could not find the ColdFusion component or interface pathtocfcfolder.sale.GetSale

However if I just instantiate the component without the method it works fine like this:

<cfset Sale = New pathtocfcfolder.sale() />
<cfdump var="#Sale.GetSale(SaleID = URL.id)#" />

The GetSale function is basically this:

<cffunction name="GetSale" returntype="Query" access="public">
  <cfargument name="SaleID" type="numeric" required="true" />
  <cfstoredproc procedure="dbo.GetSale">
   <cfprocparam cfsqltype="cf_sql_integer" dbvarname="@SaleID" value="#ARGUMENTS.SaleID#"/>
   <cfprocresult name="rsSale" resultset="1"/>
  </cfstoredproc>
  <cfreturn rsSale /> <!--- returns the query from the database --->
 </cffunction>

Solution

  • Looking at what I think the intent is, your folder structure is probably something like:

    \pathtocfcfolder
    .. Sale.cfc
    page.cfm
    

    The error actually tells what the issue is: there is no GetSalecomponent.

    With New pathtocfcfolder.sale.GetSale(....), you're trying to instantiate the GetSale component in the folder pathtocfcfolder\sale\. CF doesn't know that sale is supposed to be a component. That's why Redtopia's suggestion worked. By using sale(), you've told ColdFusion that the folder to look in is pathtocfcfolder and start with the sale component because of () functions/methods. Then CF immediately calls GetSale(...).

    This isn't really what New is supposed to do. It's meant to instantiate components (or objects) and not functions/methods of those components. It can (or at least appear to do so), but that doesn't mean it should. Especially if you are going to use other functions inside of your object. Instantiate the component once and reuse it.

    If you only wanted to use a function from inside a component once and then throw the component away, you can use cfinvoke to call that function. Otherwise, you'd want to instantiate the object and call the functions on that object as you need them.

    On a side note, since you are using ColdFusion 2018, you can use new component("pathtocfcfolder.Sale") (instead of new pathtocfcfolder.Sale()) to instantiate the component and then use Sale.GetSale(...) to call your function. The 2018 syntax makes your intent a little clearer.

    I'll also add back in my caution about using URL variables directly in code. Sending them to a Stored Procedure will handle much of the SQL Injection issues, but I'm of the opinion that the first thing a user-supplied variable should do is go through at least some basic sanitation and validation. People can be very not nice to your aplication.