How to conditionally pass arguments to an instance of a CFC?
Asked Answered
A

2

5

I am currently using the <cfinvoke> tag to invoke CFCs and pass them arguments. This is really convenient because I can use tags to pass in only the parameters that I want like such:

<cfinvoke component="pathtofolder.imagehandler" method="SomeMethod" argumentcollection="#VARIABLES#" returnvariable="ImageHandlerResult">
<cfif structkeyexists(ARGUMENTS, 'Argument1')>
<cfinvokeargument name="Parameter1" value="#ARGUMENTS.Argument1#" />
</cfif>
<cfif structkeyexists(ARGUMENTS, 'Argument2')>
<cfinvokeargument name="Parameter2" value="#ARGUMENTS.Argument2#" />
</cfif>
<cfif structkeyexists(ARGUMENTS, 'Argument3')>
<cfinvokeargument name="Parameter3" value="#ARGUMENTS.Argument3#" />
</cfif>
</cfinvoke>
<cfreturn ImageHandlerResult /> <!--- how do you get this using createObject/new method? --->

If I use the new() or createObject() methods to create an instance of the CFC and then call the methods within this newly created instance I'm not able to conditionally pass arguments. I get errors at runtime.

<cfset ImageHandler = new pathtofolder.imagehandler()/>
<cfset ImageHandler.SomeMethod(
    <cfif StructKeyExists(ARGUMENTS, 'Argument1')>
    Parameter1 = ARGUMENTS.Argument1
    </cfif>
    <cfif StructKeyExists(ARGUMENTS, 'Argument2')>
    Parameter2 = ARGUMENTS.Argument2
    </cfif>
<cfif StructKeyExists(ARGUMENTS, 'Argument3')>
    Parameter3 = ARGUMENTS.Argument3
    </cfif>
)/>

How can I pass in arguments conditionally using the above method? Should I use the cfinvoke method on the new instance - in which case what is the point in making an instance and then using cfinvoke again when I could just stick to using cfinvoke on the actual CFC directly?

Assess answered 30/10, 2018 at 16:55 Comment(3)
Are you calling cfinvoke inside another function? If not, there isn't really a true arguments scope. You're creating a structure named arguments. And I believe, since it's a structure, you may also run into pass-by-reference issues.Tonsillitis
Are you calling this from inside a function?Tonsillitis
Yes I am @Shawn. It occurs within a CFC that takes processes posts submitted by a user. See here #53064956Assess
N
6

You can use argumentCollection. Argument collection is a structure and each key will be deconstructed as individual arguments.

<cfset ImageHandler = new pathtofolder.imagehandler()>
<cfset args = {}>
<cfif StructKeyExists(ARGUMENTS, 'Argument1')>
  <cfset args.Parameter1 = ARGUMENTS.Argument1>
</cfif>
<cfif StructKeyExists(ARGUMENTS, 'Argument2')>
  <cfset args.Parameter2 = ARGUMENTS.Argument2>
</cfif>
<cfif StructKeyExists(ARGUMENTS, 'Argument3')>
  <cfset args.Parameter3 = ARGUMENTS.Argument3>
</cfif>

<cfset ImageHandler.SomeMethod(argumentCollection=args)>
Nissensohn answered 30/10, 2018 at 17:5 Comment(8)
Thanks for this. But I already use argumentCollection to pass the Variables scope variables. How would I pass both variables scope and arguments?Assess
Your example does not show that you are passing in argumentCollection, so I’m not sure what you’re referring to when you say you are. Also, you may want to look at using optional arguments in your method definition, which can be assigned a default value.Terra
Once i have ran <cfset ImageHandler.SomeMethod(argumentCollection=args)> how do I <cfreturn> the result back to the calling page? If use '<cfinvoke>' I get a 'returnvariable' that I place in a '<cfreturn returnvariable/>' and send it back to the callerAssess
Your returned value will be in myReturnValue for myReturnValue = ImageHandler.SomeMethod(argumentcollection=args), provided your SomeMethod() has a return.Tonsillitis
@Tonsillitis thank you. so it should be <cfset ImageHanderResult = ImageHandler.SomeMethod(argumentCollection=args)> right?Assess
Yes. And then ImageHandlerResult would hold the return valued of SomeMethod(). But make sure that SomeMethod() actually returns what you want.Tonsillitis
@Tonsillitis yes I have wrapped ImageHanderResult in a cfif tag to check if the structkeyexists and if it has a len() before returning it.Assess
You want to make sure it returns something every time, and if you need to, check for existence further down the workflow.Tonsillitis
N
1

There is a similar way which can be used to pass conditional attributes to ColdFusion tags. Following is an example for a <cfmail> tag.

<cfset local.cfmailArguments = {
  to : '[email protected]',
  from : '[email protected]',
  subject : 'Passing custom smtp',
  type : 'html',
}>
<!--- There are custom mail settings available in session.SMTPDetails --->
<cfif structkeyexists(session, "SMTPDetails")>
  <cfset local.cfmailArguments['from'] = session.SMTPDetails.FromEmail>
  <cfset local.cfmailArguments['server'] = session.SMTPDetails.Server>
  <cfset local.cfmailArguments['username'] = session.SMTPDetails.UserName>
  <cfset local.cfmailArguments['password'] = session.SMTPDetails.Password>
  <cfset local.cfmailArguments['port'] = session.SMTPDetails.Port>
  <cfset local.cfmailArguments['usetls'] = session.SMTPDetails.TLS>
  <cfset local.cfmailArguments['usessl'] = session.SMTPDetails.SSL>
</cfif>
<cfmail attributecollection="#local.cfmailArguments#">
  Your mail content.
</cfmail>

Instead of having to manage different tags in each conditions.

Nissensohn answered 1/11, 2018 at 5:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.