0

I understand that in ColdFusion, explicit scoping is a Good Thing. Since learning this, I try to explicitly scope all variables, even for variables like queries, for example, <cfquery name="local.myQuery"> or <cfquery name="variables.myQuery">.

My question is how to do explicit scoping when defining a function inside a .CFM page, which will be used only on the same page. Can I do <cffunction name="variables.myFunction"> or something similar?

krubo
  • 5,969
  • 4
  • 37
  • 46
  • 2
    Scoping applies to variable names - not function names. Plus, for your `cfquery` example, if the query is not being run inside a function, the most appropriate scope is not `local` - it's `variables`. – Dan Bracuk Aug 28 '19 at 03:23
  • 1
    *"...outside the function"* There is no such thing. The [local scope](https://helpx.adobe.com/coldfusion/developing-applications/the-cfml-programming-language/using-coldfusion-variables/about-scopes.html) contains variables that are defined *inside* a function - so it doesn't even exist outside of a function. – SOS Aug 28 '19 at 20:01
  • @Ageax Hm...I see. Ok, edited now. – krubo Aug 29 '19 at 01:03
  • To clarify, unless you are dealing with a special case like threads, the default scope is `variables`. – SOS Aug 29 '19 at 01:55

3 Answers3

0

The best practice would be to take that function out of the cfm page and put it into a cfc class, then create an instance of the class from your page and use it.

Everything else will eventually lead to tears. Coldfusion will throw an error if you try to define a function with the same name twice (so if you ever replicate this function in some other cfm that includes or is included by this page, it will crash).

Roughly speaking, this should be your Thing.cfc file:

<cfcomponent>
  <cffunction name="myFunction">
  </cffunction>
</cfcomponent>

and this should be your cfm:

<cfset thing = new Thing()>
<cfset thing.myFunction()>

myFunction will be scoped only to the Thing class, and you will be able to define a function of the same name in other classes, or even override it in descendant classes.

Tim Jasko
  • 1,532
  • 1
  • 8
  • 12
  • Is it ok to use `` without explicit scoping? I thought this can cause issues if, for example, the page is called with `?thing=1` and now the unscoped use of `thing` ends up unexpectedly in the `url` scope. – krubo Aug 29 '19 at 00:42
  • 1
    No, it wouldn't. It would create two variables: `url.thing` and `variables.thing` (unscoped variables are automatically placed in the `variables` scope). Code referencing `thing` (without a scope), would return `variables.thing`, due to CF's precedence rules for [evaluating unscoped variables](https://helpx.adobe.com/coldfusion/developing-applications/the-cfml-programming-language/using-coldfusion-variables/about-scopes.html). That said, omitting the scope can create ambiguity, so explicitly scoping variables is a better practice. – SOS Sep 17 '19 at 14:12
0

Posting my own answer with what I've found so far. The link from @Ageax's comment led me to this ColdFusion documentation on Specifying the scope of a function. It says:

When you define a UDF, ColdFusion puts it in the Variables scope.

You can assign a UDF to a scope the same way you assign a variable to a scope, by assigning the function to a name in the new scope. For example, the following line assigns the MyFunc UDF to the Request scope:

1: <cfset Request.MyFunc = Variables.MyFunc>

The way I understand this, it means that I should simply use <cffunction name="myFunction"> to define the function, but I should use explicit scoping when calling it, like variables.myFunction().

Community
  • 1
  • 1
krubo
  • 5,969
  • 4
  • 37
  • 46
  • 1
    Honestly, I don't usually scope functions, since unless you're doing something exotic, they're always in the variables scope. Side note, this isn't related to your your question, but ... the docs left out a very important consideration about assigning a function to a variable. The assignment removes the function from it's context which may break the function. For example if `myFunc()` depends on a variable `variables.foo`, and you execute it from another context - where that variable doesn't exist - the function will break. – SOS Aug 29 '19 at 02:21
  • In a CFC you can "scope" your functions. Private methods are called with `this.`, public methods vith `variables.`. – Bernhard Döbler Aug 29 '19 at 09:13
0

Despite the fact that functions in ColdFusion are able to live in different scopes (default is variables) you should not change that or play with it. Just use components to apply encapsulation or leave then in the variables scope. If you try to define a function with the same name (in the same .cfm or in included ones), you will get an error and that should be fine, so you can't overwrite a function like that.

You should scope the variables inside a function. You don't do that scoping the name of the function but scoping the variables inside then. Good practice would be using the local scope or the var prefix.

<cffunction name="foo">
 <cfset var a = 123>
  <cfset local.b = 345>
</cffunction>

In Lucee you can define globally the whole scope of a function using localmode="modern"

function foo()localmode="modern"{...}
SOS
  • 6,430
  • 2
  • 11
  • 29
barrenec
  • 1
  • 1