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

Reply via email to