Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at BFusion / BFLEX 2010 (Bloomington, Indiana) with: Ben Dalton and Simon Free
Ben Nadel at BFusion / BFLEX 2010 (Bloomington, Indiana) with: Ben Dalton@bendalton ) and Simon Free@simonfree )

ColdFusion Custom Tag CALLER Scope Uses Special Structure Notation

By Ben Nadel on
Tags: ColdFusion

From what I can see, CALLER scope structure notation is a special form of structure notation. Let's take a look at an example. Let's assume that we have a custom tag called my_tag.cfm:

  • <!--- Param attributes values. --->
  • <cfparam name="" />
  • <cfparam name="ATTRIBUTES.value" />
  • <!--- Set value in caller scope. --->
  • <cfset CALLER[ ] = ATTRIBUTES.value />
  • <!--- Make sure tag does not execute twice. --->
  • <cfexit method="EXITTAG" />

All this tag does is take a variable name and value and sets the value into the variable name in the caller scope. Let's call this as a custom tag and send in a variable name:

  • <!--- Create an empty structure. --->
  • <cfset REQUEST.Data = StructNew() />
  • <!--- Create two keys for testing. --->
  • <cfset REQUEST.Data[ "anne" ] = "" />
  • <cfset REQUEST.Data[ "sarah" ] = "" />
  • <!--- Set value. --->
  • <cf_my_tag
  • name="REQUEST.Data.anne"
  • value="hot"
  • />
  • <!--- Set value. --->
  • <cf_my_tag
  • name="REQUEST.Data.sarah"
  • value="crazy hot!"
  • />

This tag executes as you would expect it to. The two values are stored into their appropriate variables as in the CFDump below:


CFDump - CALLER Scope  

However, let's take a look at the line that actually sets the value:

  • <!--- Set value in caller scope. --->
  • <cfset CALLER[ ] = ATTRIBUTES.value />

If you think about what the is, it's a string value that stands for a variable name. In one case above, I am passing in the value "REQUEST.Data.sarah". That means that the custom tag line can evaluate to:

  • <!--- Set value in caller scope. --->
  • <cfset CALLER[ "REQUEST.Data.sarah" ] = ATTRIBUTES.value />

And, in fact, if you replace that line of code, it does run correctly, but only storing values into REQUEST.Data.sarah. But look at what is going on here: CALLER is a struct that is using a variable name as a key. Let's look at a quasi-parallel example that does not include a custom tag:

  • <!--- Create another empty structure. --->
  • <cfset REQUEST.Girls = StructNew() />
  • <!--- Create two keys for testing. --->
  • <cfset REQUEST.Girls[ "ashley" ] = "" />
  • <cfset REQUEST.Girls[ "julie" ] = "" />
  • <!---
  • Set value. Try to mirror this:
  • <cfset CALLER[ ] = ATTRIBUTES.value />
  • --->
  • <cfset REQUEST[ "Girls.ashley" ] = "hot" />
  • <cfset REQUEST[ "Girls.julie" ] = "super hot!" />

In this example, we are trying to treat the REQUEST scope in the same way that we treat the CALLER scope. We are passing it a variable name in the hopes that it will evaluate properly as it did in the custom tag. However, as you can in the following CFDump, it does not:


CFDump - REQUEST Scope to Mirror CALLER Scope  

Instead, what it did is use the variable name as a whole to create a key in the REQUEST scope. Honestly, this is how I though the CALLER scope would have worked as well, but it must be some sort of special notation that I am unaware of. Anyway, it's worth noting that you can use CALLER slightly differently than any other scope that I can see, unless I am missing something critical.

Reader Comments


I am not sure if this is a bug... if it was, how would you be able to store return data into a nested variable?

I suppose, if it is a bug, you could do something like:

<cfset "CALLER.#ARGUMENTS.return#" = XYZ />

That should work as expected and would allow you to store into nested objects within the caller scope.


can a custom tag call a javascript function in the caller or access any div tag from the caller.



There is no Javascript being run on the server (most likely). As such, you can't execute Javascript from within a custom tag.