1

I want to easily put an argument's struct contents into the variables scope for all functions of a component. 'Title' is one of the searchitems struct.

<cffunction name="setSearch" acces="public" returntype="void">    
     <cfargument name="searchitems" type="struct" required="true" />
     <cfset variables = arguments.searchitems>
     <cfset variables.test = "yo">           
</cffunction>

<cffunction name="testit" acces="public" returntype="void">
    <cfdump var="#variables.test#"><br>
    <cfif isdefined('variables.test')>found in variables.test  </cfif>
    <cfif isdefined('variables.variables.test')>found in variables.variables.test </cfif>
    <hr>
    <cfdump var="#variables.title#"><br>
    <cfif structkeyexists(variables,'title')>found in variables.title with structkeyexists </cfif>
    <cfif structkeyexists(variables.variables,'title')>found in variables.variables.title with structkeyexists</cfif>
    <cfif isdefined('variables.title')>found in variables.title </cfif>
    <cfif isdefined('variables.variables.title')>found in variables.variables.title</cfif>
</cffunction>

however running this gives:

yo
found in variables.test

mytitletext
found in variables.variables.title with structkeyexists
found in variables.variables.title 

I find this strange that title can be dumped or output as variables.title but it can't be detected with isDefined or structkeyexists. Is there a more efficient way to assign

<cfset variables = arguments.searchitems> 
James A Mohler
  • 11,060
  • 15
  • 46
  • 72
Beth B
  • 59
  • 2
  • 2
    First and foremost, you need to understand that any object's private methods reside in the variables scope, and doing it the way you are will be wiping them from the CFC instance. You probably want to abstract things out a bit, eg: `variables.searchItems = arguments.searchItems`, so you don't arbitrarily blow away other stuff in the variables scope. Will look @ the rest of your logic later... – Adam Cameron Sep 12 '13 at 10:30
  • The simplest way is to use properties. Some might consider this to be a fashion faux pas in the programming context, but it's still the simplest way. – Dan Bracuk Sep 12 '13 at 11:55
  • When you set `variables = arguments.searchitems` you're actually creating a _new_ struct called "variables" in the variables scope, ie `variables.variables`. In other words, your `variables` struct does not replace the real `variables` _scope_. When you dump `variables.title` CF is actually giving you `variables.variables.title`. The scope is being inferred. `StructKeyExists( variables,"title" )` fails because there is no `title` variable in the variables _scope_ (although it exists in your `variables` struct). Does that make any sense? – CfSimplicity Sep 14 '13 at 09:15

2 Answers2

2

Use the component's "this" scope.

<cfcomponent>

<cfset this.myArgs = StructNew()>
<cfset this.test = "">


<cffunction name="setSearch" acces="public" returntype="void">    
     <cfargument name="searchitems" type="struct" required="true" />
     <cfset this.myArgs= arguments>
     <cfset this.test = "yo">           
</cffunction>

</cfcomponent>
Lucas
  • 1,402
  • 1
  • 12
  • 18
  • 1
    I wouldn't use the `this` scope because it's _public_, i.e. values can be changed from outside the component. See http://www.cutterscrossing.com/index.cfm/2013/9/11/Legacy-Code-Part-13-An-Object-Lesson for a recent explanation. – CfSimplicity Sep 14 '13 at 08:42
1

I'd recommend following Adam's advice and keeping your searchitems in their own separate struct in the variables scope rather than as individual items. That way you don't risk overwriting other variables.

Test.cfc

<cfcomponent>

    <cffunction name="init">
        <!--- Set up a separate empty container for the searchitems to be available to all functions --->
        <cfset variables.searchitems = StructNew()>
        <cfreturn this>
    </cffunction>

    <cffunction name="setSearch" returntype="void">    
        <cfargument name="searchitems" type="struct" required="true">
        <!--- Fill the container with the struct passed into this function --->
        <cfset variables.searchitems = arguments.searchitems>
    </cffunction>

    <cffunction name="dumpSearchTitle" returntype="void">
        <cfdump var="#variables.searchitems.title#">
    </cffunction>

</cfcomponent>

index.cfm

<cfscript>
    request.searchitems = StructNew();
    request.searchitems.title = "mytitletext";
    test = CreateObject( "component", "test" );
    test.setSearch( request.searchitems );
    test.dumpSearchTitle();
</cfscript>

However, if it's really important to have the individual searchitems in the variables scope, then you could append them to the variables scope. The third, false parameter of StructAppend ensures you don't overwrite existing variables.

Test.cfc

<cfcomponent>

    <cffunction name="init">
        <cfreturn this>
    </cffunction>

    <cffunction name="setSearch" returntype="void">    
        <cfargument name="searchitems" type="struct" required="true">
        <cfset StructAppend( variables,arguments.searchitems,false )>
    </cffunction>

    <cffunction name="dumpSearchTitle" returntype="void">
        <cfdump var="#variables.title#">
    </cffunction>

</cfcomponent>
CfSimplicity
  • 2,338
  • 15
  • 17