In the "Getting Started" pages, layouts are treated as static HTML. Often, however, we need to get data from our model layer into our layout components. Layout components provide a bit of a cheat in order to accomplish this without (technically) breaking encapsulation.
It should be noted, however, that while this doesn't technically break encapsulation (as component references are passed in), it does violate the spirit of encapsulation.
All layout components in Neptune extend (directly or indirectly) "_framework.layout". Let's look at the "init" method of this component:
<cffunction name="init" access="public" returntype="any" output="no"> <cfargument name="CGI" type="struct" required="yes"> <cfargument name="Factory" type="any" required="no"> <cfset initInternal(ArgumentCollection=Arguments)> <cfreturn This> </cffunction>
OK. This might not seem that useful at first as all of the action happens in "initInternal", but it does tell us a few things that are helpful to know. We know that layout components expect two arguments: "CGI" (the CGI scope) and "Factory", which is optional.
Now to the relevant piece in "initInternal":
<cfif StructKeyExists(Arguments,"Factory")> <cfset Variables.Factory = Arguments.Factory> </cfif>
The "Factory" argument is really a bit of a cheat. Neptune passes in Application.Framework.Loader, which is a reference to the AppLoader component, which itself has a reference to every component that it creates. This effectively means that it is a reference to any service in your site.
So, if you want to reference Application.CMS (without technically breaking encapsulation), you could reference it with "Variables.Factory.CMS".
Although this still essentially breaks encapsulation, it is still the recommended approach. Admittedly, the benefits of this over direct reference to Application scope are limited, but so is the cost.