Getting something really strange that I just can’t work out.
I have 3 methods within a CFC (guest.cfc):
- save
- create
- update
I pass an argumentCollection to the save method.
saveGuest = objGuest.save(argumentcollection=guestStruct)
If it includes an Identier, it passes the argumentCollecion to the update method, if it doesn’t then it passes the collection to the create method.
This is working fine when called from one place int the app, but when I created a new call to the save method, the create method works fine, but if an ID is passed in the update method is called I receive an error that the UPDATE variable does not exists.
But, if I change the way I call it by creating an object of the cfc, it works..
so..
saveObject = update(argumentCollection = arguments;
Does not work. Receive an error that the update variable does not exist.
saveObject = createObject("component",'guest').update(argumentCollection = arguments);
DOES work.
note that both these calls are occuring within the guest.cfc itself.
This issue doesn’t occur when I pass a form struct to the save method, but does occur when I pass it a standard struct (constructed from an XML import).
Very strange.
Anyone have any ideas on what might causing this?
EDIT 24 April – Added Code for guest.cfc
<cffunction name="save" output="false" access="remote" hint="save guest">
<cfargument name="title" type="any" required="false" default="" />
<cfargument name="first_name" type="any" required="false" default="" />
<cfargument name="surname" type="any" required="false" default="" />
<cfargument name="dob" type="any" required="false" default="NULL" />
<cfargument name="partner_first_name" type="any" required="false" default="" />
<cfargument name="partner_surname" type="any" required="false" default="" />
<cfargument name="partner_dob" type="any" required="false" default="NULL" />
<cfargument name="address_1" type="any" required="false" default="" />
<cfargument name="address_2" type="any" required="false" default="" />
<cfargument name="address_3" type="any" required="false" default="" />
<cfargument name="city" type="any" required="false" default="" />
<cfargument name="state" type="any" required="false" default="" />
<cfargument name="postcode" type="any" required="false" default="" />
<cfargument name="country" type="any" required="false" default="" />
<cfargument name="phone_bh" type="any" required="false" default="" />
<cfargument name="phone_ah" type="any" required="false" default="" />
<cfargument name="phone_mob" type="any" required="false" default="" />
<cfargument name="fax" type="any" required="false" default="" />
<cfargument name="email" type="any" required="false" default="" />
<cfargument name="business" type="any" required="false" default="" />
<cfargument name="notes" type="any" required="false" default="" />
<cfargument name="referer" type="any" required="false" default="" />
<cfargument name="prospect" type="any" required="false" default="" />
<cfargument name="occasion" type="any" required="false" default="" />
<cfargument name="occasion_date" type="any" required="false" default="NULL" />
<!---pass to Create or Save--->
<cfif NOT isdefined("arguments.guest_id") OR arguments.guest_id EQ "0">
<cfset saveObject = create(argumentCollection = arguments) />
<cfelse>
<cfset saveObject = update(argumentCollection = arguments) />
</cfif>
<cfreturn saveObject>
</cffunction>
<!---CREATE--->
<cffunction name="create" output="false" access="private" returntype="struct" hint="Create a New Item">
<cfargument name="provider_id" type="any" required="false" default="#session.providerID#" />
<cfargument name="ext_ref_id" type="any" required="false" default="NULL" />
<cfargument name="tstamp" type="any" required="false" default="#session.tStamp#" />
<cfif isValid('date',arguments.occasion_date)>
<cfset iOccasionDate = createODBCDateTime(arguments.occasion_date)>
<cfelse>
<cfset iOccasionDate = "NULL">
</cfif>
<cfset returnStruct = StructNew()>
<cfquery name="insertGuest" datasource="#Application.ds#">
INSERT INTO guest (provider_id, ext_ref_id, title, first_name, surname, full_name, partner_first_name, partner_surname, partner_full_name, address_1, address_2, address_3, city, state, postcode, country, phone_bh, phone_ah, phone_mob, fax, email, company, notes, referer, prospect, occasion, occasion_date, tstamp)
VALUES (#provider_id#, #ext_ref_id#, '#arguments.title#', '#arguments.first_name#', '#arguments.surname#', '#arguments.first_name# #arguments.surname#', '#arguments.partner_first_name#', '#arguments.partner_surname#', '#arguments.partner_first_name# #arguments.partner_surname#', '#arguments.address_1#', '#arguments.address_2#', '#arguments.address_3#', '#arguments.city#', '#arguments.state#', '#arguments.postcode#', '#arguments.country#', '#arguments.phone_bh#', '#arguments.phone_ah#', '#arguments.phone_mob#', '#arguments.fax#', '#arguments.email#', '#arguments.company#', '#arguments.notes#', '#arguments.referer#', '#arguments.prospect#', '#arguments.occasion#', #iOccasionDate#, #CreateODBCDateTime(tstamp)#)
</cfquery>
<cfquery name="guest" datasource="#Application.ds#">
SELECT max(guest_id) as id
FROM guest
WHERE provider_id = #provider_id#
</cfquery>
<cfset returnStruct.id = #guest.id#>
<cfreturn returnStruct>
</cffunction>
<!---UPDATE--->
<cffunction name="update" output="false" access="private" returntype="struct" hint="Update an existing item">
<!---general details--->
<cfquery name="update" datasource="#Application.ds#">
UPDATE guest
SET provider_id = provider_id
<cfif isdefined("arguments.title")>
,title = '#arguments.title#'
</cfif>
<cfif isdefined("arguments.first_name")>
,first_name = '#arguments.first_name#'
</cfif>
<cfif isdefined("arguments.surname")>
,surname = '#arguments.surname#'
</cfif>
<cfif isdefined("arguments.full_name")>
,full_name = '#arguments.full_name#'
</cfif>
<cfif isdefined("arguments.dob")>
,dob = #formDate2odbcDate(arguments.dob)#
</cfif>
<cfif isdefined("arguments.partner_first_name")>
,partner_first_name = '#arguments.partner_first_name#'
</cfif>
<cfif isdefined("arguments.partner_surname")>
,partner_surname = '#arguments.partner_surname#'
</cfif>
<cfif isdefined("arguments.partner_full_name")>
,partner_full_name = '#arguments.partner_full_name#'
</cfif>
<cfif isdefined("arguments.partner_dob")>
,partner_dob = #formDate2odbcDate(arguments.partner_dob)#
</cfif>
<cfif isdefined("arguments.address_1")>
,address_1 = '#arguments.address_1#'
</cfif>
<cfif isdefined("arguments.address_2")>
,address_2 = '#arguments.address_2#'
</cfif>
<cfif isdefined("arguments.address_3")>
,address_3 = '#arguments.address_3#'
</cfif>
<cfif isdefined("arguments.city")>
,city = '#arguments.city#'
</cfif>
<cfif isdefined("arguments.state")>
,state = '#arguments.state#'
</cfif>
<cfif isdefined("arguments.postcode")>
,postcode = '#arguments.postcode#'
</cfif>
<cfif isdefined("arguments.country")>
,country = '#arguments.country#'
</cfif>
<cfif isdefined("arguments.phone_bh")>
,phone_bh = '#arguments.phone_bh#'
</cfif>
<cfif isdefined("arguments.phone_ah")>
,phone_ah = '#arguments.phone_ah#'
</cfif>
<cfif isdefined("arguments.phone_mob")>
,phone_mob = '#arguments.phone_mob#'
</cfif>
<cfif isdefined("arguments.fax")>
,fax = '#arguments.fax#'
</cfif>
<cfif isdefined("arguments.email")>
,email = '#arguments.email#'
</cfif>
<cfif isdefined("arguments.subscribe_email_broadcast")>
,subscribe_email_broadcast = '#arguments.subscribe_email_broadcast#'
</cfif>
<cfif isdefined("arguments.company")>
,company = '#arguments.company#'
</cfif>
<cfif isdefined("arguments.notes")>
,notes = '#arguments.notes#'
</cfif>
<cfif isdefined("arguments.prospect")>
,prospect = '#arguments.prospect#'
</cfif>
<cfif isdefined("arguments.occasion")>
,occasion = '#arguments.occasion#'
</cfif>
<cfif isdefined("arguments.occasion_date")>
,occasion_date = #formDate2odbcDate(arguments.occasion_date)#
</cfif>
WHERE guest_id = #arguments.guest_id#
</cfquery>
<cfset returnStruct = structNew()>
<cfset returnStruct.id = arguments.guest_id>
<cfreturn returnStruct>
</cffunction>
In CF, when inside a function and you write things like
<cfset iOccasionDate = ... >and<cfquery name="insertGuest" ...>you are creating these in the global variables scope of that CFC/template.You need to write either
<cfset var iOccasionDate = ... >or<cfset local.iOccasionDate = ... >or<cfquery name="local.insertGuest" ...>to ensure they are created in the local variable scope for the function, and don’t overwrite other variables.Your specific problem is because you have this:
So you’re overwriting your update function with an update query.
A few quick things to note:
The local scope works in CF9 and above. If you’re in CF8 or below you need to mimic it by writing
<cfset var local = StructNew() />at the top of your function.If you use Railo or OpenBD there are settings to change the default behaviour to always create in local scope (which avoids the need for var/local scoping), but ACF does not have this option (yet?)
Use cfqueryparam! – Simon has already mentioned this, but it’s important enough to be repeated. You should always handle data based on where it will be used – to prevent intentional and accidental injection attacks – and for cfquery that means using cfqueryparam.