Search code examples
coldfusionuser-defined-functionscoldfusion-9

ColdFusion User Defined Functions from included file aren't available


I am using ColdFusion 9.

I am including a UDF library (UDF_Library.cfm) that has just a few functions it in. When I try to access the functions, I get an error that says "Variable POPUP is undefined". The library is included in the Application.cfc as the first part of the onRequestStart method.

Here's how I include the library:

<cfscript>
// INCLUDE UDF_LIBRARY
include "/UDF/UDF_Library.cfm";
</cfscript>         

Here is the contents of the library:

<cfscript>
function popUp() {
    return "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
}
</cfscript>         

I know the function works. When I just write out the function directly into the file and call the function, it works fine.

<cfscript>
writeOutput(popUp());
function popUp() {
    return "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
}
</cfscript>         

Why is the function not seen when included in a UDF in the application.cfc file before any part of the page is loaded?


Solution

  • I think the missing information in all the guidance here is a suggestion to understand how variables scoping works, which has nothing to do with in which Application.cfc event handler one might declare a function.

    Application.cfc event handlers do not impart any magical persistence on things initially declared within them: one still needs to put any declared variables or functions into a scope appropriate to how they'll be accessed. Declaring a variable within onRequestStart (or onRequest) does not magically make that variable available to everything in the request. And a function is just a variable.

    When one includes a file - like you are doing - any variable declarations (and accordingly function declarations) reside in whatever scope one puts them in. If one declares a function, and does nothing more with it, then the function exists only in the variables scope.

    If one declares a function in onRequestStart(), which is just a method within the instance of Application.cfc which is created at the beginning of every request, then the function will be put in the variables scope of that CFC instance. And will last precisely as long as the life of that CFC instance. As far as the execution of onRequestStart() is concerned, the CFC instance lasts as long as it takes to run onRequestStart(). So not long.

    On the other hand, onRequest() is not an event handler (like onRequestStart() is), it's an event interceptor: it takes place instead of the event it intercepts. In general, onRequest() includes - literally - the template being requested. So the template being requested runs in the same memory space as the CFC instance including it (via onRequest()) so the included template shares the variables scope of the CFC instance, and accordingly the variables scope availed to onRequest(). So if onRequest() includes a UDF library which declares a bunch of functions in the variables scope... that's the same variables scope as the main requested file included in the onRequest() interceptor. Same as any other CFC instance method including files.

    So... the upshot of this is that simply including a file full of functions in onRequestStart() does not do what you want, for - hopefully now - obvious reasons. Equally including a file full of functions in onRequest() does not impart magical persistence to them: they're just put in the variables scope. That means they will be accessible to the requested template, and any template it includes. They will not be available to any custom tag, nor any CFC instance used within that request.

    If one wants a function (or "some functions") to be available to any code within a request, one needs to put those functions into the request scope (or another shared scope). And the way to do this is the same as with any variable:

    request.something  = somethingElse;
    

    That's it. That's the only way of doing it. Including a file full of functions will not be a complete solution for what you wish to do, irrespective of how you include it.