I'm a big fan of the ColdBox framework. I think the core MVC part of the framework is very intuitive and easy to get started with (the loads of documentation also doesn't hurt). And then as you get more comfortable with it and want to implement more advanced techniques, you can take advantage of the vast array of tools and extension capabilities that it provides, which is why (as Luis Majano frequently points out) it's more than just a framework, but a also a software development toolkit.
Be that as it may, I believe it's always helpful to look at different frameworks and methodologies for ideas and inspiration. The other day, I was checking out the ColdFusion on Wheels site. I was perusing their intro docs and video tutorials and one of the cool things about that framework is that views are implicitly called based on what event is requested. On their obligatory 'hello world' tutorial, they give this as an example of a controller named say.cfc:
This is a controller component called say.cfc with a single method named 'hello'. Now, there's nothing going on in this particular event. But if you go to this url:
http://localhost/say/hello
the framework will look for a view file in the views/say/ directory called 'hello.cfm', and if it finds one, it will be displayed. So views can be called implicitly based on the controller/event combination that's requested. Now in my ColdBox development, I usually organize my views in subfolders named for the event handlers they are in (event handler components in ColdBox are analogous to controller components in CFWheels). So I thought about how I could implement something like this in ColdBox. It's actually quite easy.
In your ColdBox configuration, you can designate events that get fired at specific points along the framework/request life cycle. Some are analogous to ColdFusion's onRequestStart, onRequestEnd, onSessionStart... you get the idea. The advantage to using the ColdBox versions is that you get to tap into the framework's functionality. So, to implement implicit views in ColdBox, I added this line of code in my onRequestStart handler:
This way, the view is automatically set whenever the event is requested. If you make sure to organize your vew files in subfolders named for their corresponding event handlers (and name your view files after your events), you don't have to explicitly set your view in your handler. Of course, there may be situations where you want to call a different view than the one called implicitly. In those cases you simply set your view explicitly within your event handler using the event.setView('viewname') method.
There are a couple of things to keep in mind when you use this technique. First, if you're on a UNIX-based OS, case-sensitivity kicks in. So, if your url is:
http://localhost/say/hello
make sure your view is named 'hello.cfm', not 'Hello.cfm' or you'll get an error saying that the view file can't be found. Second, I've already mentioned that you can effectively override the implicit view by calling a different view explicitly in your event handler. However, sometimes you'll also want to render the view without a layout (for example, if the view wil be used in an AJAX call). For this, you would normally use the nolayout argument of the setView method:
But this won't work. The view will still be shown within the default layout. It turns out that this happens because an internal variable is set with the layout when the view is first set in the onRequestStart method and the nolayout argument is then skipped when the view is set again in the event handler. Framework author Luis Majano has logged this bug for the version 2.6.1 release. (Update on August 18, 2008: this is no longer an issue as of the 2.6.1 final release.) Until then, there are a couple of ways to work around this. One is manually "emptying" the Layout variable in the request collection:
Another method is to have an AJAX html layout (see the ColdBox docs for an explanation) and then explicitly setting this layout in your event handler method:
Or you can declare implicit layout/view assignments in your ColdBox configuration (again, see the docs). That's it! That's all you have to do if you want to have CFWheels-like implicit views in your ColdBox application. Keep in mind that this will work whether you're using SES urls with url rewriting (as in my example urls above), without url rewriting (i.e. index.cfm/handler/action), or with query string urls (/index.cfm?event=handler.action). On a related side note, ColdBox's SES functionality is based on Adam Fortuna's ColdCourse project which, in turn, is based on the url routing implementation used in ColdFusion on Wheels. Turns out it's a small world when it comes to CF frameworks.
Also, I'd like to point out that I later found out that Adam Fortuna blogged about ColdBox implicit views a while back, so this idea is definitely not a new one, but I decided to blog about it anyway.
Aug 1, 2008 at 5:45 AM Hi Tony,
Good post!
> make sure your view is named 'hello.cfm', not 'Hello.cfm' or you'll get an error saying that the view file can't be found.
Just use:
<cfset event.setView("#LCase(event.getCurrentHandler())#/#LCase(event.getCurrentAction())#") />
and give your views lowercase names.
Ronan
Aug 6, 2008 at 7:25 AM Good tip, Ronan!