How to include UDF_library in application.cfm?

487 views Asked by At

I am using ColdFusion 8.0.1

I am working on an existing application that has thousands of pages. I am trying to include a library of new UDFs in my application.cfm file.

I addedd this line to application.cfm:

<!--- UDF library include --->
<cfinclude template="UDF/udf_library.cfm">

The UDF library includes other files that contain UDFs, like this:

<cfinclude template="udf_powerreview.cfm">

I have functions in the udf_powerreview.cfm file, such as:

// CREATE POWER REVIEWS SNIPPET
function createPRSnippet(Page_ID) {
    LOCAL.Page_ID =  ARGUMENTS.Page_ID;
    if (isNumeric(LOCAL.Page_ID) && LOCAL.Page_ID > 0) {
        LOCAL.Snippet = "<div class='pr_snippet_product'><script type='text/javascript'>var pr_snippet_min_reviews = 0; POWERREVIEWS.display.snippet(document, { pr_page_id : '#LOCAL.Page_ID#' });</script></div>";
    } else {
        LOCAL.Snippet = "";
    }
    return LOCAL.Snippet;
}

The debugging tool says that UDF/udf_library.cfm and udf_powerreview.cfm are being successfully included.

The problem is when I call the function in another page, I get an error that says that function doesn't exist. When I can copy the function and put it directly into the page that it is used in and it works just fine. And, I do not get the error "routines can not be declared twice".

In every site that I build, I create a udf_library.cfm or udf_library.cfc in the exact same manner. They always work fine.

What might prevent the functions from being available and accessed? Is there an application setting that needs to be set?

3

There are 3 answers

2
Dave Ostrander On BEST ANSWER

It's a page scope issue. Don't think of the Application.cfm as an include on all your pages, just know that it runs first. Somethings it initializes will carry over to your existing page scope and some things won't. Using an Application.cfc instead of an application.cfm takes care of much of the ambiguity.

To make your UDF's available to your whole application, I would suggest using a "Singleton" Design pattern. First take your UDF's and put them in a CFC format. This will make them more portable.

in your application.cfm you could put the following lines:

<cfif NOT isdefined('session.udf_powerreview') or isdefined('url.resetudf')>
  <cfset  session.udf_powerreview = createobject('Component','udf.udf_powerreview')/>
  <!--- this 'udf.udf_powerreview' represents the physical path udf/udf_powerreview.cfc --->
</cfif>

I'm stuffing it in the session scope instead of the application scope, becuase you won't have an good way of resetting the application scope if you modify your UDF's.

Either way, once this is in your application.cfm you should be able to see your functions on any page.

<cfdump var="#session.udf_powerreview#">
0
BKK On

Here is one strategy that I use. This basically calls the UDFs "on demand". It won't reimport the UDFs if it already exists. You do however have to have named arguments however, otherwise you'd have to strip out the UDFName out of the argument collection. I'm worried however that argument order might not be preserved, I haven't investigated that.

application.cfm

<cfapplication 
    name="udftest_001" />

<cffunction name="udf">
    <cfargument name="udfname" type="string" required="true">
    <cfif NOT isDefined(udfname)>
        <cfinclude template='./udfs/#udfname#.cfm'>
    </cfif>
    <cfset tempfunc = variables[udfname]>
    <cfreturn tempfunc(argumentCollection=arguments)>
</cffunction>

index.cfm

<cfoutput>
#udf(udfname='testUDF',firstname='John',lastname='Smith')#<br/>
#udf(udfname='testUDF',firstname='Betty',lastname='Ford')#<br/>
</cfoutput>

/udfs/testudf.cfm

<cfscript>
function testUDF() {
    return 'Hello ' & arguments.firstname & ' #arguments.lastname#';
}
</cfscript>
2
ale On

I suspect something is up with relative paths.

Can you make "UDF" a mapping? Then you can do

<cfinclude template="/UDF/udf_library.cfm">