tags:

views:

156

answers:

3

Is there a way to specify the component path in the tag?

I am using ColdFusion Components for my application. My application has several folders, however, and each time I want a CFC to work, I have to save it in the same directory as those files that need access. This results in my creating of several CFC files that are identical.

Is there a way to store my CFCs in one directory and make it work across my site?

+2  A: 

For ColdFusion 9

FileSystem

/
  lib/
    DataAccess.cfc
    IndexingService.cfc
  app/
    Application.cfc
    index.cfm

File: /app/Application.cfc

component {
  root = goUpDirectory(2, GetCurrentTemplatePath());
  This.mappings["/lib"] = "#root#/lib";
  This.mappings["/app"] = "#root#/app";

  function goUpDirectory(levels, path) {
    for(levels = levels; levels >= 1; levels -= 1) {
      path = GetDirectoryFromPath(path);
      path = Left(path, Len(path) - 1);
    }
    return path;
  }
}

File: /app/controllers/UsersController.cfc

component {
  ...
  da = new lib.DataAccess();
  ...
}

For ColdFusion 8

Same as above, just using CreateObject instead of new, <cfcomponent /> instead of component { }, etc.

Justice
Justice, many thanks for taking the time to outline the code.
Mel
+3  A: 

There are a few things you can do here. I would recommend you put the components where they make sense (root/com, or root/models, or whatever) and then reference them from your application base.

In the ColdFusion administrator, you can set up a mapped path to your Application root and reference your components from that path.

myObject = createObject('component','nameOfMyMapping.models.service.answerStackOverflowQuestions');

You can also perform some logic in your Application.cfm / Application.cfc to find the application's root dynamically. This method does not require special permissions and will work if you relocate your application to another enviroment. A quick Google turned up a blog post by Peter Freitag with a function that will do just this. Just be sure to replace the .cfm if you are using an Application .cfc. http://www.petefreitag.com/item/630.cfm

CFLib.org also has a method which looks like it will find the root path for you. http://www.cflib.org/udf/GetRootPath

Once you have your root path stored in a variable things get easy.

myObject = createObject('component','#myRoot#.models.service.answerStackOverflowQuestions');

Finally, many frameworks have made this, and many other common taks, very simple. You can choose just about any ColdFusion framework. Someone already invented the wheel ;).

Have fun!

Aaron Greenlee
Justice's code works just as well.
Aaron Greenlee
Note also that CF searches the CustomTags path for components. This is useful if you're on a hosted plan and can't make your own server mappings.
Al Everett
Thanks Aaron. I found Frameworks to be completely unfriendly to new users, and they're not an option for me. I was looking at Fusebox, and the installation was so confusing I gave up. It's easy to unzip the files, but instructions placing them according to the installation method I prefer were very incoherent, asking me to place files in directories without clearly specifying what they are; and asking to download to sets of files without explaining what each does and where to put it.
Mel
Mel, The ColdBox framework has a great deal of documentation, a book, and lots of apps. You can even get training! If you are looking for a framework to start with, ColdBox would be my choice. Buy the book and walk though it. You won't regret it. https://www.createspace.com/3411525
Aaron Greenlee
+2  A: 

As others have noted, you can do interesting things with mappings and functions that locate the root of your application, but at the heart of your question is general path specification.

I would suggest you read the portion of the Using ColdFusion Components documentation titled Specifying the CFC location.

Essentially, what it says is that if your application lives at http://example.com/myApp/ and you have a page at http://example.com/myApp/foo/bar/fubar.cfm that wants to use the component at:

/myApp/foo/components/library/fubar.cfc

then fubar.cfm should do something like this:

<cfset fubar=createObject("component", "myApp.foo.components.library.fubar") />

You take the path of the file and replace slashes with dots (aka "dot notation"), and also drop the ".cfc" from the file name of the component you want to load.

In addition, you can use named mappings (as Aaron described), so if you create a mapping called /components that points to /myApp/foo/components/ then your createObject call would look like this:

<cfset fubar = createObject("component", "components.library.fubar") />

The same dot-notation paths can be used in <cfinvoke />, as part of the component attribute:

<cfinvoke component="components.library.fubar" ... />
Adam Tuttle
Components do not necessarily map, in any way, to a URL. They may, but more than likely, they may not. Best practice indicates that components should be moved outside the web-accessible directories unless they are intended to be web-accessible components.
Justice
Justice and Adam, first of all, many thanks. I have a question: Moving CFCs to outside of the webroot is not practical for shared enviroments; am I correct?
Mel
@Justice, yes you are correct. I intentionally left that part out to avoid confusion. @Mel, yes, shared hosting environments typically do not provide a good way to move components outside of the web root.
Adam Tuttle
It would probably depend on the shared environment. For example, if in your shared environment your directory is at `/home/Justice/code/` but you were also permitted to specify a relative path from that directory to the webroot for your account like `app/` putting your webroot at `/home/Justice/code/app/`, then you can do it. If you're stuck with the account webroot being the same as the account root, then you're stuck with putting CFCs within the webroot.
Justice