Sounds good, Jason. Thanks for the overview and examples! This is making more and more sense each hour!
Rick > -----Original Message----- > From: Jason Durham [mailto:[EMAIL PROTECTED] > Sent: Monday, June 23, 2008 11:55 AM > To: CF-Talk > Subject: RE: Clarification Required Concerning CFC... > > As others have mentioned... don't fight OO. :) It takes a bit of time > to adjust but it will all come together and you'll be a more productive > developer as a result. > > As someone mentioned, the variable scope is local to the page (doesn't > matter if the file ends in cfc or cfm). You aren't *including* a > component, you're creating a copy of it in memory. When you initialize > each of the objects, sometimes they require variables to function (DSN > is a good example). Take this as an example... > > Let's say you want to group all of your data access (queries) functions > into one CFC. All of these functions merely get/insert/update based > upon arguments sent to them. While they may return different results, > they are essentially 'reset' after they are executed. Since you're > going to have several methods that all depend on the same DSN, you can > inject the DSN into the init() function and store the variable in a > scope that is available to all methods on that 'page'. Since this CFC > merely returns queries, you could store this CFC in a scope that allows > it to persist across many page requests. For the purpose of learning, > think about it this way... > > > From Application.cfc... > > <cffunction name="onApplicationStart()" returntype="boolean" > output="false"> > > <!--- Store DB info to be injected into objects that need it ---> > <cfset var dsn = "myDsn" /> > <cfset var dbUser = "myUser" /> > <cfset var dbPwd = "myPwd" /> > > <!--- Create all of my objects that perform CRUD operations ---> > <cfset oUserGateway = > createObject("component","path.to.UserGateway").init(myDsn,myUser,myPwd) > /> > <cfset oHomeGateway = > createObject("component","path.to.UserGateway").init(myDsn,myUser,myPwd) > /> > <cfset oNewsletterGateway = > createObject("component","path.to.NewsletterGateway").init(myDsn,myUser, > myPwd) /> > > ... include any other application stuff you want ... > > </cffunction> > > When you're application loads, you create variables to hold your DB > credentials and DSN. Then you inject variables into each of your CFCs > that communicate with that DB. Now let's look inside one of those > Gateway objects. > > From UserGateway.cfc... > > <!--- Pseudo constructor method ---> > <cffunction name="init" access="public" output="no" > returntype="UserGateway"> > <cfargument name="DSN" type="string" required="yes" hint="ColdFusion > datasource name." /> > <cfargument name="dbUsr" type="string" required="yes" > hint="ColdFusion datasource's username." /> > <cfargument name="dbPwd" type="string" required="yes" > hint="ColdFusion datasource's password." /> > > <cfset VARIABLES.dsn = ARGUMENTS.dsn /> > <cfset VARIABLES.dbUsr = ARGUMENTS.dbUsr /> > <cfset VARIABLEs.dbPwd = ARGUMENTS.dbPwd /> > > <cfreturn this /> > </cffunction> > > <!--- Get list of users by is_Active database field ---> > <cffunction name="getUsers" access="public" output="no" > returntype="query"> > <cfargument name="isActive" type="boolean" required="no" > default="false" hint="Limit results to users marked active in > database."/> > > <!--- var all variables I want to disappear after this method runs > ---> > <cfset var qOut = "" /> > > <!--- Get users ---> > <cfquery name="qOut" datasource="variables.dsn" > username="variables.dbUsr" password="variables.dbPwd"> > SELECT * > FROM tbl_User > WHERE 0=0 <cfif Arguments.isActive> AND is_Active = 1</cfif> > </cfquery> > > <cfreturn qOut /> > </cffunction> > > There are a couple of OO practices going on here. In Application.cfc, > you have injected the DB config/credentials into the init() method. The > init() method simply passes those arguments into the variables scope > when the object is created. All of the methods from within that > component have access to the variables scope. Therefore... all of them > have access to the DB config/credentials. So now you've got a > Application.oUserGateway object hanging around in memory for you to use > to perform CRUD operations on Users. When it's time for you to get a > list of users, you can simply invoke the method on any template in the > application by doing this... > > From within XYC.cfm.... > > <!--- Get active users from database ---> > <cfset qActiveUsers = Application.oUserGateway.getUsers(true) /> > > The <cfinvoke> equivalent is this... > <cfinvoke component="Application.oUserGateway" method="getUsers" > returnvariable="qActiveUsers" isActive="true" /> > > You see how much extra typing is involved with <cfinvoke>, which is why > I prefer the cfset way to do it. Anyway, that invocation is accessing > the UserGateway from memory, running getUsers with an argument value of > 'true'. That may seem like quite a bit of typing just to get a user > list huh? The beauty is, you can reuse that UserGateway object on > another app because it knows *nothing* about *anything* that hasn't been > explicitly provided. If your DB password changes, you make ONE change > (onApplicationStart) and reload the app. That is a basic form of > encapsulation. If application requires new user fields in the database, > or is_active changes from Boolean to another datatype, it's much easier > to search/replace/modify all of your queries in one place. > > Setting up the OO model takes some time. What works best for you might > not work best for us. This topic seems pretty popular and it doesn't > seem to be too hard to get opinions on it. Keep trying to work through > it brotha. :) Keep in mind, this example is just for general CRUD > components. You don't want to load every object into the Application > scope (especially on a shared server). Try to stay away from using > CGI, session, request, application, or server scopes from within your > components. Instead, pass those values into a method via an argument. > > > -----Original Message----- > From: Rick Faircloth [mailto:[EMAIL PROTECTED] > Sent: Saturday, June 21, 2008 10:11 PM > To: CF-Talk > Subject: RE: Clarification Required Concerning CFC... > > > That would make less sense. The Variables scope is the local scope for > any > > CF program. CFM and CFC files are both CF programs. > > It just seems to make little sense to have two scopes named the same > thing > which have nothing to do with each other. It would be like me creating > two variables with the same name, but having different values. Now that > would > be confusing! > > I could have variables.time in a cfc that is 4pm, but variables.time > outside > a cfc which has the value of 4am, right? > > If so, a scope exclusive to cfc's would seem to make more sense. > cfcVariables.time vs variables.time... instantly recognizable. > > That's just the way it seems as I get started with cfc's... > > Rick > > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Adobe® ColdFusion® 8 software 8 is the most important and dramatic release to date Get the Free Trial http://ad.doubleclick.net/clk;203748912;27390454;j Archive: http://www.houseoffusion.com/groups/CF-Talk/message.cfm/messageid:307965 Subscription: http://www.houseoffusion.com/groups/CF-Talk/subscribe.cfm Unsubscribe: http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4