B and E Blog

Just a couple of opinionated nerds talking about ColdFusion, PHP, and technology in general.

B and E Blog header image 2

ColdFusion Including Sub-Applications

May 30th, 2008 · 2 Comments · ColdFusion, Programming

Ben Nadel has an interesting question on his blog about including sub-applications from within an existing CF application, and having the relevant sub-level Application.cfc fire off.

This is doable in a fairly simple manner but which relies on a barely-documented feature of ColdFusion, and the fact that the sub-level Application.cfc fires is completely undocumented, and may even be unintentional!

Here’s how you can do it, but because we’re wandering into a pretty hazy gray area here, I wouldn’t go using this unless you don’t have much other choice.

Application.cfc:

  1. <cfcomponent>
  2. <cffunction name="onRequest">
  3. <cfargument name="filename">
  4. <cfset var fileToInclude = arguments.filename>
  5. <cfif structKeyExists(request, "currentInclude")>
  6. <cfset fileToInclude = request.currentInclude>
  7. <cfset StructDelete(request, "currentInclude")>
  8. </cfif>
  9. <cfoutput><b>#GetCurrentTemplatePath()#</b> is including <b>#fileToInclude#</b>:
  10. <blockquote></cfoutput>
  11. <cfinclude template="#fileToInclude#">
  12. <cfoutput></blockquote>
  13. </cfoutput>
  14. </cffunction>
  15. <cffunction name="include">
  16. <cfargument name="filename">
  17. <cfset var basePath = "">
  18. <cfset var thisPath = "">
  19. <cfset var path = "">
  20. <cfif left(filename, 1) neq "/">
  21. <!--- Relative paths need to be turned into fully qualified paths --->
  22. <cfset basePath = GetDirectoryFromPath(getCurrentTemplatePath())>
  23. <cfset thisPath = CGI.PATH_TRANSLATED>
  24. <cfset path = mid(CGI.SCRIPT_NAME, 1, len(CGI.SCRIPT_NAME) - (len(thisPath) - len(basePath)))>
  25. <cfset request.currentInclude = path & filename>
  26. <cfelse>
  27. <cfset request.currentInclude = filename>
  28. </cfif>
  29. <cfset getPageContext().include(request.currentInclude)>
  30. </cffunction>
  31. </cfcomponent>

Then you can do the below and if it has an Application.cfc, that application.cfc will be invoked.
  1. <cfset include("subfolder/file.cfm")>

The caveat though is that CGI scope will still contain the variables from the source page - for example, CGI.SCRIPT_NAME will still be the script name in the URL. As a result, context-sensitive functions like ExpandPath() will operate relative to the root file being called - meaning you might not get the results you’re expecting.

Also the code above will only work 1 sub-application level deep; you’d have to tweak it if you wanted a sub-application within a sub-application, but by that point, zounds, what are you doing man?!?

The good news is that even if the sub-application executes a <cfabort>, execution will return to the calling page, so that sub-app can’t abort your own page.

Tags: ··

2 responses so far ↓

  • 1 Ben Nadel // May 30, 2008 at 1:42 pm

    @Eric,

    Interesting. The GetPageContext().Include() is an odd beast. I have used it from time to time with good success and other times I have used it, it has totally bombed out. I am still not 100% what it actually does. When I first learned about it, I was waaaay off. Luckily Charlie Arehart cleared it up:

    http://www.bennadel.com/index.cfm?dax=blog:376.view

    But even now, I am not 100% what it does. It seems like a bit of black magic box. I see what you are doing though. Seems cool.

  • 2 Eric // May 30, 2008 at 2:16 pm

    It is a bit of black magic that’s for sure.

    As I understand it, it executes a form of sub-request, but does so without redoing the steps of creating a new page context (CGI, URL, FORM, etc vars among other things).

    The Macrodobe documentation on this uses the example of passing execution to a JSP page. So it’s any executable context that the java server is willing to call. In fact this might even be an artifact of coldfusion.runtime.NeoPageContext (the type of object returned by getPageConext()) being a subclass of javax.servlet.jsp.PageContext.

    Because in CF8 some of these things (especially CGI) are immutable, it means

Leave a Comment