This is CF11.
I have a collection of dependencies that I must cfinclude at the top of every CFM and CFC we run. It is a single cfinclude that recursively includes other files. This has worked on every page load for many years; mostly legacy CFM pages, and some newer CFCs. However, I've recently tried to do this from within an Application.cfc, and while it resolves the top-most include, it fails to resolve the children includes. I get the typical cfinclude relative-path error message:
... Note: If you wish to use an absolute template path (for example, template="/mypath/index.cfm") with
CFINCLUDE, you must create a mapping for the path using the ColdFusion Administrator. Or, you can use
per-application settings to specify mappings specific to this application by specifying a mappings
struct to THIS.mappings in Application.cfc. ...
From the CFC itself (called from the browser with URL x/index.cfm), I have:
getBaseTemplatePath() = x/index.cfm
getCurrentTemplatePath() = x/Application.cfc
expandPath("./") = x
And from the top-most include:
getBaseTemplatePath() = x/index.cfm
getCurrentTemplatePath() = y/TheInclude.cfm
expandPath("./") = x
Other CFCs in this application - those siblings of Application.cfc that cfinclude the same file - produce the same path expansions, but also successfully resolve the child includes. Am I doing something wrong, is this a bug in Application.cfc, or ...?
This is a bug and has been verified by Adobe.
Bug report CF-4207025.
Maybe it's the content of what is inside those includes.
Check this:
https://helpx.adobe.com/in/coldfusion/cfml-reference/application-cfc-reference/application-variables.html
Related
I am using this code for display my page in page content in MURA 6.1
<div>[mura]$.dspInclude('display_objects/custom/main.cfm')[/mura]</div>
But it gives me the error below:
Note: If you wish to use an absolute template path (for example,
template="/mypath/index.cfm") with CFINCLUDE, you must create a
mapping for the path using the ColdFusion Administrator. Or, you can
use per-application settings to specify mappings specific to this
application by specifying a mappings struct to THIS.mappings in
Application.cfc. Using relative paths (for example,
template="index.cfm" or template="../index.cfm") does not require the
creation of any special mappings. It is therefore recommended that you
use relative paths with CFINCLUDE whenever possible. Could not find
the included template
/muraWRM/default/includes/display_objects/custom/main.cfm.
The physical path is
[siteid]/default\includes\themes\rescue\display_objects
Thanks in advance
This should work
<div>[mura]$.dspInclude('themes/rescue/display_objects/custom/main.cfm')[/mura]</div>
Your include is being called from the includes folder, so you need to include the themes folder and the rescue folder to get to the right path.
For consistency across themes, you might want to use Mura's setting for the theme name, but I would have to look that up.
If you are ok hard coding it, this should work just fine.
I am trying to use mappings for the first time and I am having some issues. In my CFadmin I created a mapping which goes like this:
Logical Path:
/email_sender
Directory Path:
E:\sites\Example.Com\cf_modules\autoresponders\Emails\emailLists
I am trying to access the include file from a .cfc. Inside my cfc I have an include file which is in the same folder and it works just fine but that include file is tying to access another include file based on the information I am passing through.
The include file inside the component has this code in it.
<cfmail from="#emailData.sender#" to="#surveymain.email#" subject="#subject#" type="HTML" >
<cfinclude template="#emailData.includePath#" >
</cfmail>
Just to be more clear this is my total filesystem:
access.cfm -> some.cfc -> include_1 (works) -> include_2 (issue with
the path)
I have a try/catch which emails me the errors and it is located inside the include_1.
How can I use the mapping that I created to finally be able to access my include file?
Please note that after emailLists I have dynamic folders which change depending on which client I am trying to send the email to. So the end result of the path would be:
E:\sites\Example.Com\cf_modules\autoresponders\Emails\emailLists\client_A\email_template.cfm
I tried using my mapping by doing this
<cfinclude template="/email_sender/#emailData.includePath#" >
which gave me this error:
The path to the CFC must be specified as a full path, or as a relative
path from the current template, without the use of mappings.
Also, I tried including a full path in the cfinclude whic also resulted in the following error:
Note: If you wish to use an absolute template path (for example, >template="/mypath/index.cfm") with CFINCLUDE, you must create a
mapping for the path using the ColdFusion Administrator. Or, you can
use per-application settings to specify mappings specific to this
application by specifying a mappings struct to THIS.mappings in
Application.cfc. Using relative paths (for example,
template="index.cfm" or template="../index.cfm") does not require the
creation of any special mappings. It is therefore recommended that you
use relative paths with CFINCLUDE whenever possible.
Any help/suggestion would be much appreciated
Edit:
After restarting the server the version that worked was this one:
<cfinclude template="/email_sender/#emailData.includePath#" >
Thanks to those who replied.
Some questions, rather than some answers.
Did you set the mapping in CFAdmin or in Application.cfc?
What do you get if you run the code below?
#expandPath("/email_sender")#
What is the value of #emailData.includePath#?
What is the value of this: #expandPath("/email_sender#emailData.includePath#")#?
Can you provide us with the exact text of the error messages, rather than vaguely describing them.
What is the value of #fileExists(expandPath("/email_sender#emailData.includePath#"))#?
If you can update your question with that info, you'll either spot where you're going wrong, or we can help to work out what the story is
Something like this happened to me once before. Essentially we edited the xml file, rather than using the admin interface. It wasn't until our sys admin restarted the server until we realized why the mapping hadn't taken. So have you restarted the server since you added the mapping?
Note: If you wish to use an absolute template path (for example,
template="/mypath/index.cfm") with CFINCLUDE, you must create a
mapping for the path using the ColdFusion Administrator.
I went to the administration page but not sure what to put in here.
I'm pretty new to coldfusion. anyone got any ideas why this would be happening.
CFINCLUDE uses relative paths in relation to the file where the cfinclude is, so if want to include a file in another directory, 1. it has to be inside your wwwroot (or the root directory, or subdirectories) of your site, 2. you can go to other directories by doing ... hope this helps a little bit. If you want to include a file that is outside of your wwwroot, then you'll need to map that directory in Coldfusion Administrator using the same syntax above when you do include it.
To add a mapping, open your coldfusion administrator.
Server Settings > Mappings
There are 2 paths. Logical and Directory.
Logical can be anything you want, and directory is where it maps to.
eg. you might have a folder below your web root which stores email templates mapped as:
logical path: /emails
directory path: /var/www/mycfapp/content/includes/emails
You can <cfinclude template="/emails/forgotPass"> from any cf template and the mapping would get picked up.
You can use the mappings for new object creation too. Lets pretend forgotPass is a cfc.
fp = new emails.forgotPass();
// if you have funky characters in there, eg dash, just quote it.
fp = new "emails.forgot-pass"();
Mappings also work when extending cfcs. With one small exception. No leading slash.
component extends="emails/forgotPass" {
// ...
}
Im pretty sure mappings are detected first, so if you have a folder with the same name it might not get picked up.
In cf9 you can also specify your mappings in your Application.cfc, instead of coldfusion administrator, which affects all applications on your server. eg.
this.mappings["/emails"] = "/var/www/mycfapp/content/includes/emails";
You'll need to tick the Enable Per App Settings option on the cfadmin Settings page.
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec0b63c-7fd5.html
Previously (and locally) I've placed the fusebox5 directory in the web root, and then applications from anywhere in the tree have been able to access it. I'd previously also used Application.cfm rather than .cfc.
In this environment I don't have access to the webroot and the FB files don't really need to be that far down anyway, so I had planned to store them alongside the applications. Am I right in thinking that index.cfm is overlooked if Application.cfc is in use (and therefore there's no point changing the cfinclude value to be eg. ../fusebox5/)? If so, how can I include the framework without having Fusebox in the root or in a mapping? Error is:
Could not find the ColdFusion Component or Interface fusebox5.Application.
No, your app is still going to need index.cfm. What you'll need is a cf application mapping for Fusebox in your Application.cfc. Look at Ray Camden's Application.cfc template for an example of setting application specific mappings.
You can run Fusebox 5+ in a subfolder of your app root. It just may not be the most obvious thing to make it work.
Unfortunately, you cannot create a dynamic mapping for extending Application.cfc because your Application.cfc has not yet been instantiated - you get a chicken vs. egg scenario. You can't create the mapping to Fusebox because your Application.cfc didn't start, you can't start your Application.cfc because it can't find the component it's supposed to extend.
THIS IS A BUG IN COLDFUSION 8. ColdFusion should look for mappings in this order:
Mapped folders from the CF Administrator
Sub directories off the current directory
Sub directories off the web root called
It does this when you use CreateObject(), but not when you use the Extends attribute on cfcomponent.
The easiest solution is to use your Application.cfc like you would for any application, then include fusebox from your index.cfm. Your folder structure would look like this:
/myapp/fusebox5/
/myapp/index.cfm
-- consists of <cfinclude template="fusebox5/fusebox5.cfm" />
Your index.cfm file will not be ignored as long as you don't intercept the request with Application.cfc's OnRequest, or if you use OnRequest, make sure you include the intended target (which will almost always be index.cfm anyway).
If you want to not require index.cfm to do the include, you can have your Application.cfc's OnRequest method do the cfinclude.
<cffunction name="onRequest">
<cfinclude template="fusebox5/fusebox5.cfm">
</cffunction>
You still may need an index.cfm so your web server won't give a directory listing or 404, but it's ok if the file is empty.
In Application.cfc:
<cfscript>
this.mappings = {}; //create a new structure to store app-specific mappings
this.mappings["Fusebox"] = expandPath('./Fusebox'); //add mapping
</cfscript>
I want to extend a CFC in a different directory and I have a couple of options, but can't figure out how to do this:
A) Use a dynamic mapping (this will have to be dynamic based on the site, e.g. for the live site it would be cfc.myPackage.MyCFC but on a dev site it would be myCfcRoot.myPackage.MyCFC) - I've tried putting expressions into the extends bit but obviously CF doesn't like that, e.g. :
<cfcomponent name="MyComponent" extends="#config.cfcRoot#.BaseComponent">
or
<cfcomponent name="MyComponent" extends="#GetRealPath(../BaseComponent.cfc)#">
B) Provide a relative path (somehow) to the CFC to extend.
I fear that I can't do this, but I'm hoping that there is something I've missed.
Daniel is basically correct, you need a mapping. However, there are 3 workarounds.
CFCs will pick the current path as a relative root mapping, so if your CFCs are all in the same directory, you can just say
<cfcomponent name="MyComponent" extends="Example">
Or if your components are in subdirectories from the current cfc, you can access it:
<cfcomponent name="MyComponent" extends="subdirectory.Example">
Second, if you are running on ColdFusion 8, you can define a mapping in your application.cfc using the mappings struct like this:
<cfset this.mappings["/MyApp"] = expandPath(".") />
There are two good references for Application.cfc, first, Ray Camden's example Application.cfc which just gives a nice view of what goes where, then the CF8 Live Docs application settings page, which has a section on mappings along with some good comments.
Finally, you can use the built-in mapping of your web root, so if your application is in a subdirectory named "MyApp" off the web root, your root mapping will be "MyApp". Let's say you correctly put your components in:
wwwroot\MyApp\com\MyApp\example.cfc
The mapping to this cfc in this case will be:
MyApp.com.MyApp.Example
And using your example, you can extend like this:
<cfcomponent name="MyComponent" extends="MyApp.com.MyApp.Example">
Anything else, such as if your components are outside of the web root, or if you are not sure what the folder structure of your finished application will be, and you will need to set a mapping in the CF Administrator.
Now this is only tested in cf8 so other engine could differ.
if you want to use relative paths to extend applications you can but your have to start them with a "/.". For instance you can do this to extend an application.cfc from your web root into directory below you webroot:
<cfcomponent output="false" extends="/.application">
<!--- whatever code you have --->
</cfcomponent>
now let's say I have the following paths in my application:
[webroot]/1/1a
[webroot]/2
let's say that the application.cfc in [webroot]/1/1a extends the application.cfc in [webroot]. now I want to place an application.cfc in [webroot]/2 and extend the application.cfc in [webroot]/1/1a. all i would have to do in my [webroot]/2/application.cfc is the following:
<cfcomponent output="false" extends="/./1/1a/application">
<!--- whatever code you have --->
</cfcomponent>
hope this makes sense.
Unless the CFC is in the same directory as the calling script the CFC must be located and referenced from a path relative to a "Mapping".
I have found that sometimes you need to make sure that "/" is mapped to your document root of your webserver and that becomes the base for all relative paths. Or you can setup a mapping for a CFC directory that hold all of your common CFCs.
This screen is found in the ColdFusion Admin under "Server Settings" -> "Mappings".
In regards to Method B. It can be done using an additional file in your example. It's one extra file per cfc that you want to extend per directory that you want to extend from.
The 3 files that are required.
/somepathtobasecomponent/basecomponent.cfc (your base component file)
/pathtoworkingcfc/function.cfc (the file with the extends attribute)
/pathtoworkingcfc/basecomponent_extend.cfc (the new file that will do the extending)
/somepathtobasecomponent/basecomponent.cfc
Nothing to change here. This stays the same.
/pathtoworkingcfc/function.cfc
in the cffunction tag set the extends to extends="basecomponent_extend"
/pathtoworkingcfc/basecomponent_extend.cfc
Sole content of the file is a cfinclude
<cfinclude template="/somepathtobasecomponent/basecomponent.cfc">