coldfusion
This article presents an introduction to ColdFusion components (CFCs). For developers seeking to take their skills to the next level, CFCs are an invaluable addition to the toolkit, allowing the adoption of a more professional approach to web application development.
本文介绍了ColdFusion组件(CFC)。 对于寻求将其技能提升到更高水平的开发人员,CFC是该工具包的宝贵补充,可以采用更专业的方法来进行Web应用程序开发。
Ushered in with ColdFusion MX 6, CFCs have enjoyed strong support from the developer community ever since. These days, ColdFusion 8 provides both significant and subtle improvements to the way CFCs work, which include major new features such as close Ajax integration, not to mention greatly enhanced performance.
自从ColdFusion MX 6引入以来,CFC一直得到开发人员社区的大力支持。 如今,ColdFusion 8对CFC的工作方式进行了重大且细微的改进,其中包括主要的新功能,例如紧密的Ajax集成,更不用说大大提高了性能。
Being able to develop using CFCs allows us to write highly maintainable and flexible ColdFusion applications and reuse more code. Even better, it also permits us to leverage great capabilities in ColdFusion, both new and existing, such as automatic web service generation and powerful Ajax tags.
能够使用CFC进行开发使我们能够编写高度可维护和灵活的ColdFusion应用程序,并重用更多代码。 更好的是,它还使我们能够利用ColdFusion的强大功能,包括新功能和现有功能,例如自动Web服务生成和强大的Ajax标签。
This article will cover the following topics:
本文将涵盖以下主题:
- what a CFC is 什么是CFC
- why CFCs are useful and worth learning 为什么氟氯化碳有用和值得学习
- how to write a CFC 如何编写CFC
- how and where to start using CFCs in applications 如何以及在何处开始在应用程序中使用CFC
- an introduction to other great features in ColdFusion that use CFCs 介绍使用CFC的ColdFusion的其他重要功能
- tips for developers new to CFCs 面向CFC的开发人员的技巧
要求 (Requirements)
software
软件
You can choose between Adobe ColdFusion 8’s Trial, Developer, Standard, or Enterprise Editions — ColdFusion 8 allows you to try before you buy.)
您可以在Adobe ColdFusion 8的Trial,Developer,Standard或Enterprise版本之间进行选择-ColdFusion 8允许您在购买前进行尝试 。)
You’ll need a text editor or IDE of your choice — Adobe Dreamweaver and Eclipse/Adobe FlexBuilder with the Adobe ColdFusion Eclipse Extensions are popular options, but any text editor can also be used.
您需要选择一个文本编辑器或IDE-带有Adobe ColdFusion的Eclipse扩展是Adobe Dreamweaver和Eclipse / Adobe FlexBuilder ,但也可以使用任何文本编辑器。
sample code
样例代码
A set of sample code for using the sample BookClub database that shipped with CF8 is available here.
此处提供了一组使用CF8附带的示例BookClub数据库的示例代码。
prerequisite knowledge
必备知识
Users are assumed to be familiar with basic ColdFusion development, including user-defined functions — refer to the ColdFusion documentation if you need a general refresher or specific reminder.
假定用户熟悉基本的ColdFusion开发,包括用户定义的功能-如果需要常规更新或特定提示,请参阅ColdFusion文档 。
什么是ColdFusion组件? (What Is a ColdFusion Component?)
ColdFusion components (CFCs) are a way of grouping related functions and data together in the one file, regardless of where they’re needed throughout our application. Some CFCs model a particular piece of data; others provide functions for accessing external data. We’ll focus on the latter in this article.
ColdFusion组件(CFC)是一种在一个文件中将相关功能和数据分组在一起的方法,无论在整个应用程序中它们在何处都需要。 一些CFC对特定的数据进行建模。 其他提供访问外部数据的功能。 在本文中,我们将重点讨论后者。
When we work with ColdFusion components, we’re really using a form of object oriented programming (OOP). If you haven’t been involved with any OOP before, don’t feel intimidated. You don’t need to be familiar with the object oriented features of ColdFusion in order to read, understand, and make use of this article and ColdFusion components.
当我们使用ColdFusion组件时,实际上是在使用一种面向对象的编程(OOP)形式。 如果您以前从未参与过任何OOP,请不要感到害怕。 您无需熟悉ColdFusion的面向对象功能即可阅读,理解和使用本文以及ColdFusion组件。
为什么ColdFusion组件有用? (Why Are ColdFusion Components Useful?)
It is possible to write sophisticated applications without components, but using CFCs in your applications help make them more maintainable and flexible while allowing greater code reuse. For anything other than a throwaway application, CFCs allow for better, more reliable, and more scalable applications.
可以编写没有组件的复杂应用程序,但是在应用程序中使用CFC可以使它们更具可维护性和灵活性,同时可以实现更大的代码重用性。 除了一次性应用程序之外,CFC还允许使用更好,更可靠和更具可伸缩性的应用程序。
These advantages arise from separating presentation logic from the business rules and data access logic. Code that generates direct output — such as ordinary HTML markup and ColdFusion tags like CFFORM
— tends to vary considerably from page to page. Business and data access logic, however, tends to remain constant.
这些优势来自将表示逻辑与业务规则和数据访问逻辑分离。 生成直接输出的代码(例如普通HTML标记和CFFORM
类的ColdFusion标签)在不同页面之间的差异往往很大。 但是,业务和数据访问逻辑往往保持不变。
CFCs allow us to capture this business and data access logic and separate it from the page markup, in effect creating a separate presentation and business layer in our application. Changing the presentation layer is less likely to affect the business layer, and vice versa. And the changes we make anywhere are likely to be smaller, since we’re no longer repeating ourselves unnecessarily. This is a good first step towards developing better architecture for our applications.
CFC允许我们捕获此业务和数据访问逻辑,并将其与页面标记分离,实际上在应用程序中创建了单独的表示层和业务层。 更改表示层不太可能影响业务层,反之亦然。 由于我们不再重复不必要的工作,因此我们在任何地方所做的更改都可能较小。 这是为我们的应用程序开发更好的体系结构的第一步。
As an additional advantage, working with ColdFusion components within our applications also allows us to take advantage of some of the more powerful features of ColdFusion, such as automatic web-service generation, Ajax controls, and the application framework.
另外一个优势是,在我们的应用程序中使用ColdFusion组件,还使我们能够利用ColdFusion的一些更强大的功能,例如自动Web服务生成,Ajax控件和应用程序框架。
样本应用 (The Sample Application)
Over the course of this article, we’ll use a sample application to see how CFCs can be used in applications. Using this BookClub database, we’ll work with a web application that, apart from tracking books and authors, also allows the user to read and post blog articles. Let’s dub our web site "BookBlogs."
在本文的整个过程中,我们将使用一个示例应用程序来查看如何在应用程序中使用CFC。 使用此BookClub数据库,我们将使用一个Web应用程序,该Web应用程序除了跟踪书籍和作者之外,还允许用户阅读和发布博客文章。 让我们复制我们的网站“ BookBlogs”。
This web site begins its life as a traditional page-based CFML application. Nearly all ColdFusion developers start with applications such as this one. This table of excerpts from the bookblogs
, members
, and blogs
folders should seem familiar:
该网站开始于传统的基于页面的CFML应用程序。 几乎所有ColdFusion开发人员都从此类应用程序开始。 从摘录的这台bookblogs
, members
和blogs
文件夹似乎应该熟悉:
/bookblogs | /bookblogs/members | /bookblogs/blogs |
---|---|---|
application.cfm | memberList.cfm | blogEntryList.cfm |
index.cfm | profile.cfm | blogEntry.cfm |
editProfileForm.cfm | newBlogEntryForm.cfm | |
updateProfile.cfm | addBlogEntry.cfm/ | |
register.cfm |
/bookblogs | /bookblogs/members | /bookblogs/blogs |
---|---|---|
application.cfm | memberList.cfm | blogEntryList.cfm |
index.cfm | profile.cfm | blogEntry.cfm |
editProfileForm.cfm | newBlogEntryForm.cfm | |
updateProfile.cfm | addBlogEntry.cfm/ | |
register.cfm |
Other folders in the application have a similar structure. Apart from separate include files for headers and footers (hidden away in the /bookblogs/layout
folder), our application is otherwise made up of a CFM file for each page the user can visit. Each of these CFM files incorporates all the required CFML code to apply business logic, access the database, and output the results. This can be seen by examining the contents of the blogEntryList.cfm
file:
应用程序中的其他文件夹具有类似的结构。 除了用于页眉和页脚的单独包含文件(隐藏在/bookblogs/layout
文件夹中)之外,我们的应用程序还由用户可以访问的每个页面的CFM文件组成。 每个CFM文件都包含所有必需的CFML代码,以应用业务逻辑,访问数据库并输出结果。 通过检查blogEntryList.cfm
文件的内容可以看出:
<cfset pageTitle = "Blogs" />
<cfinclude template="../layout/layoutQueries.cfm">
<cfinclude template="../layout/header.cfm">
<!--- Retrieve All Blog Entries --->
<cfquery datasource="#application.dsn#" name="blogEntries">
SELECT * FROM BlogEntries
ORDER BY Posted DESC
</cfquery>
<h2>All Blog Entries</h2>
<table width="90%">
<tr>
<th>Date</th>
<th>User</th>
<th>Title</th>
</tr>
<cfoutput query="blogEntries">
<tr>
<td>#dateFormat(posted)#</td>
<td>#username#</td>
<td>#title#</td>
</tr>
</cfoutput>
</table>
<cfinclude template="../layout/footer.cfm">
As we can see in the figure below, the blogEntryList.cfm
page queries the database for a complete listing of blog posts and displays them all in a simple HTML table. There’s nothing challenging about this code, except for the fact that the same SQL statement (and therefore business rule) appears with slight variations in three pages across the application.
如下图所示, blogEntryList.cfm
页面查询数据库以获取博客文章的完整列表,并将它们全部显示在简单HTML表中。 除了在同一应用程序的三个页面中出现相同SQL语句(以及业务规则)而略有不同的事实之外,此代码没有任何挑战。
Firstly, the blogEntryList.cfm
page displays a listing of all blog entries, as shown.
首先, blogEntryList.cfm
页面显示所有博客条目的列表,如图所示。
![Our BlogEntryList page](https://i-blog.csdnimg.cn/blog_migrate/cf7d2dacc096251ec14c6c2ab4700f1b.png)
As you would expect of a blog site, the homepage, or more specifically our index.cfm
page, shows a list of the most current blog entries.
就像您期望的博客站点一样,主页,或更具体地说是我们的index.cfm
页面,显示了最新博客条目的列表。
![Our index.cfm page](https://i-blog.csdnimg.cn/blog_migrate/a8234b4631c24a36c4557f565f6070de.png)
And the profile.cfm
page shows the blog entries for a particular author.
profile.cfm
页面显示特定作者的博客条目。
![Our profile.cfm page](https://i-blog.csdnimg.cn/blog_migrate/f93fc6216816fedb04262017f06eb287.png)
Coding such a simple SELECT
statement in three places during development might not seem too arduous, but it’s generally after the source code leaves our hands and must be supported that problems occur. When we return to fix a bug, or add an approval feature, integrate another data source, or simply apply the client’s latest request, we find that we need to modify and test each file. Without good documentation and a simple code base, it can be problematic to even remember which CFM files we need to update.
在开发过程中的三个地方对这样一个简单的SELECT
语句进行编码可能看起来并不那么繁琐,但是通常是在源代码移交给我们之后,并且必须支持出现问题。 当我们返回以修复错误或添加批准功能,集成另一个数据源或仅应用客户的最新请求时,我们发现需要修改和测试每个文件。 没有良好的文档和简单的代码库,即使记住我们需要更新哪些CFM文件也可能会成问题。
Naturally, there is a better way: define a BlogManager
ColdFusion component to capture all blog-related business rules and data access. And that’s exactly what we’re going to do.
当然,有一种更好的方法:定义BlogManager
ColdFusion组件以捕获所有与博客相关的业务规则和数据访问。 这正是我们要做的。
定义CFC (Defining a CFC)
The first step in integrating a ColdFusion component into our existing application is to define it. Every CFC should have clearly understood roles and responsibilities. In the case of our BlogManager
CFC, we want it to capture all of the business rules and data access logic required for the blog functionality.
将ColdFusion组件集成到我们现有应用程序中的第一步是对其进行定义。 每个氟氯化碳都应清楚地了解其作用和职责。 对于我们的BlogManager
CFC,我们希望它捕获博客功能所需的所有业务规则和数据访问逻辑。
Once this important decision about our component is made, implementing the component in ColdFusion is easy. Each CFC is defined in a single file. The filename is the desired name of the component with a .cfc
extension. In this case, we’ll define our component in a file named BlogManager.cfc
.
一旦做出了有关我们组件的重要决定,就可以在ColdFusion中轻松实现该组件。 每个CFC都在一个文件中定义。 文件名是扩展名为.cfc
的组件的所需名称。 在这种情况下,我们将在名为BlogManager.cfc
的文件中定义组件。
Our CFC can live nearly anywhere on our file system, but if it’s not in the same directory as the code that will use it, we need to refer to it using a "dot notation" syntax from the web root directory or from a mapping created in the ColdFusion Administrator.
我们的CFC几乎可以存在于文件系统中的任何位置,但是如果它与使用它的代码不在同一个目录中,则需要使用Web根目录或创建的映射中的“点表示法”语法引用它在ColdFusion管理员中。
In this instance we’ll place the BlogManager
CFC in a subfolder called components
beneath our main application folder bookblogs
, which is directly below the web root directory. We therefore use the full component name of bookblogs.components.BlogManager
to refer to the component from other locations. Separating your CFCs from other files in the web application is usually a good idea — it encourages reuse across many different pages, regardless of their location.
在这种情况下,我们将BlogManager
CFC放置在主应用程序文件夹bookblogs
下一个名为components
的子文件夹中,该子文件夹位于Web根目录的正下方。 因此,我们使用bookblogs.components.BlogManager
的完整组件名称来引用其他位置的组件。 将您的CFC与Web应用程序中的其他文件分开通常是一个好主意-它鼓励在许多不同的页面中重复使用,而无论它们位于何处。
Inside our .cfc
file we define our component. Our BlogManager
CFC will initially look something like this:
在我们的.cfc
文件中,我们定义了组件。 我们的BlogManager
CFC最初将如下所示:
<cfcomponent output="false" hint="Manages all Blog-related business rules
and data access">
<cfset this.dsn = application.dsn />
<cffunction name="getBlogEntries" access="public" returnType="query"
output="false"
hint="Returns a query containing all blog entries in
descending order by posted date">
<!--- Retrieve All Blog Entries --->
<cfquery datasource="#this.dsn#"
name="blogEntries">
SELECT * FROM BlogEntries
ORDER BY Posted DESC
</cfquery>
<cfreturn blogEntries />
</cffunction>
</cfcomponent>
Surrounding all of the code in our component is a single set of <cfcomponent>
tags. Within these tags, we can write plain CFML in the form of independent statements and familiar user-defined functions (UDFs). We have defined two attributes on the opening <cfcomponent>
tag: output
and hint
. Although optional, including both of these attributes is considered good practice.
组件中所有代码的周围是一组<cfcomponent>
标签。 在这些标记中,我们可以以独立语句和熟悉的用户定义函数(UDF)的形式编写普通的CFML。 我们在开始的<cfcomponent>
标记上定义了两个属性: output
和hint
。 尽管是可选的,但将这两个属性都包括在内是一种好的做法。
Setting the output
attribute to false
prevents extraneous code within the component from being included in your page output. The hint
attribute allows you to describe the purpose of your CFC. This does not affect the operation of your component but makes it easier for other developers to determine the role and function you have chosen for your component.
将output
属性设置为false
可以防止组件的无关代码包含在页面输出中。 hint
属性允许您描述CFC的用途。 这不会影响组件的操作,但会使其他开发人员更轻松地确定为组件选择的角色和功能。
The first element within the <cfcomponent>
tag is a single <cfset>
statement. Any code outside of functions in your component — such as this <cfset>
— will be executed whenever you first create or invoke it. This specific statement stores the name of the data source for the database, using the special this
scope, for later use by the component. As your experience with CFCs grows, you’ll find a lot of uses for storing data in your components.
<cfcomponent>
标记内的第一个元素是单个<cfset>
语句。 每当您第一次创建或调用它时,组件中函数以外的任何代码(例如此<cfset>
)都将被执行。 该特定语句使用特殊的this
范围存储数据库数据源的名称,以供组件稍后使用。 随着您对CFC的使用经验的增长,您会发现在组件中存储数据的许多用途。
Following the <cfset>
statement is our function getBlogEntries
defined by the <cffunction>
tag. Functions inside of components are often called methods. Apart from the mandatory name attribute, the other optional attributes returnType
, output
, hint
, and access
are defined. returnType
, output
, and hint
are standard <cffunction>
attributes that have the same meaning here as when used with normal UDFs.
<cfset>
语句之后是<cffunction>
标记定义的函数getBlogEntries
。 组件内部的功能通常称为方法。 除了必填名称属性外,还定义了其他可选属性returnType
, output
, hint
和access
。 returnType
, output
和hint
是标准的<cffunction>
属性,此处的含义与用于普通UDF时的含义相同。
The returnType
attribute specifies the type of data the function will return. You can set this to a simple or complex data type, such as numeric
, string
, or struct
. We can even use a component name. If we supply this value, ColdFusion will ensure the value returned from the function matches this data type. The output and hint attributes are identical to the same attributes on the <cfcomponent>
tag. The access attribute determines which code can run the function and is fully discussed in the "Security Considerations" note included later in the article. Including these attributes is optional, but is considered best practice.
returnType
属性指定函数将返回的数据类型。 您可以将其设置为简单或复杂的数据类型,例如numeric
, string
或struct
。 我们甚至可以使用组件名称。 如果我们提供此值,ColdFusion将确保函数返回的值与此数据类型匹配。 输出和提示属性与<cfcomponent>
标记上的相同属性相同。 访问属性确定可以运行该功能的代码,并将在本文后面的“安全注意事项”注释中进行全面讨论。 包括这些属性是可选的,但被认为是最佳实践。
Within the getBlogEntries
function, we use a <cfquery>
tag to pass an SQL query to the database. Notice how we can access this .dsn
variable to determine the data source name. The query in this example is fixed, but you could just as easily generate the query dynamically by using arguments passed into the method. The query result is then returned to the caller with a <cfreturn>
tag.
在getBlogEntries
函数中,我们使用<cfquery>
标记将SQL查询传递给数据库。 注意,我们如何访问此.dsn
变量以确定数据源名称。 在此示例中,查询是固定的,但您也可以使用传递到方法中的参数轻松地动态生成查询。 然后将查询结果与<cfreturn>
标记返回给调用方。
This is just the beginning of the possibilities offered by our new component. At the moment it can only retrieve a list of blog entries. Since we wanted the BlogManager
component to handle all business logic and data access relating to blogs, we also need functions to create, read, update, and delete blog entries. Although we won’t be creating them in this article, these methods can be found in the source code download.
这仅仅是我们新组件提供的可能性的开始。 目前,它只能检索博客条目列表。 由于我们希望BlogManager
组件处理与博客有关的所有业务逻辑和数据访问,因此我们还需要用于创建,读取,更新和删除博客条目的功能。 尽管我们不会在本文中创建它们,但是可以在源代码下载中找到这些方法。
For the moment, however, let’s see how we can use the BlogManager
component and the getBlogEntries
function in our applications.
但是,现在让我们看看如何在应用程序中使用BlogManager
组件和getBlogEntries
函数。
在ColdFusion应用程序中使用CFC (Using CFCs in Your ColdFusion Applications)
Within a page that needs to use the functionality defined by the component, we can execute the function with the <cfinvoke>
tag. The <cfinvoke>
tag is a powerful tag that can create components from their definition files and execute specific functions. All we need to do is specify the component, the method (remember, this is just another name for function) and where we want the result stored. Our listing of all of the available blog posts (listBlogEntries.cfm
) can be changed to use the component as shown below:
在需要使用组件定义的功能的页面内,我们可以使用<cfinvoke>
标记执行该功能。 <cfinvoke>
标记是一个功能强大的标记,可以从其定义文件创建组件并执行特定功能。 我们需要做的就是指定组件,方法(请记住,这只是函数的另一个名称)以及要将结果存储在何处。 我们所有可用博客文章的列表( listBlogEntries.cfm
)都可以更改为使用该组件,如下所示:
<cfset pageTitle = "Blogs" />
<cfinclude template="../layout/layoutQueries.cfm">
<cfinclude template="../layout/header.cfm">
<cfinvoke component="bookblogs.component.BlogManager"
method="getBlogEntries"
returnvariable="blogEntries" />
<h2>All Blog Entries</h2>
<table width="90%">
<tr>
<th>Date</th>
<th>User</th>
<th>Title</th>
</tr>
<cfoutput query="blogEntries">
<tr>
<td>#dateFormat(posted)#</td>
<td>#username#</td>
<td>#title#</td>
</tr>
</cfoutput>
</table>
<cfinclude template="../layout/footer.cfm">
As the listing shows, we have completely removed the previous <cfquery>
and replaced it with the <cfinvoke>
tag. The query that is returned the blogEntries
variable which we use to build the HTML table is exactly the same. We’ve saved a couple of lines in our page, but more importantly, our other pages can use this function too, after only a small amount of modification.
如清单所示,我们已经完全删除了以前的<cfquery>
,并用<cfinvoke>
标记代替了它。 返回的用于构建HTML表的blogEntries
变量的查询完全相同。 我们已经在页面中保存了几行,但是更重要的是,我们的其他页面也可以使用此功能,只需进行少量修改。
Our member profile page displays a list of blog entries for that specific member, and our homepage only displays a limited amount of the latest entries. If we add a couple of arguments to our getBlogEntries
function, we can make the SQL dynamic, and make the function useful enough to be called from all of the pages that need to retrieve blog entries:
我们的会员资料页面显示该特定会员的博客条目列表,而我们的首页仅显示有限数量的最新条目。 如果我们在getBlogEntries
函数中添加几个参数,则可以使SQL动态化,并使该函数足够有用,以便可以在需要检索博客条目的所有页面中调用该函数:
<cffunction name="getBlogEntries" access="public" returnType="query" output="false" hint="Returns a query containing all blog entries, optionally filtered by memberId and limited by to set number of entries (supplied from the most recent) in descending order by posted date"> <cfargument name="filterByMemberId" type="numeric" required="false" default="0" hint="If supplied, only blog entries by this member are returned" /> <cfargument name="maxEntries" type="numeric" required="false" default="9999" hint="If supplied, limits the total number of blog entries returned to this amount" /> <!--- Retrieve Blog Entries, optionally filtered by member and maximum number of rows returned ---> <cfquery datasource="#this.dsn#" name="blogEntries" maxRows="#arguments.maxEntries#"> SELECT * FROM BlogEntries, Members WHERE BlogEntries.username = members.email <cfif arguments.memberId GT 0> AND memberId = #arguments.filterByMemberId# </cfif> ORDER BY Posted DESC </cfquery> <cfreturn blogEntries /> </cffunction>
<cffunction name="getBlogEntries" access="public" returnType="query" output="false" hint="Returns a query containing all blog entries, optionally filtered by memberId and limited by to set number of entries (supplied from the most recent) in descending order by posted date"> <cfargument name="filterByMemberId" type="numeric" required="false" default="0" hint="If supplied, only blog entries by this member are returned" /> <cfargument name="maxEntries" type="numeric" required="false" default="9999" hint="If supplied, limits the total number of blog entries returned to this amount" /> <!--- Retrieve Blog Entries, optionally filtered by member and maximum number of rows returned ---> <cfquery datasource="#this.dsn#" name="blogEntries" maxRows="#arguments.maxEntries#"> SELECT * FROM BlogEntries, Members WHERE BlogEntries.username = members.email <cfif arguments.memberId GT 0> AND memberId = #arguments.filterByMemberId# </cfif> ORDER BY Posted DESC </cfquery> <cfreturn blogEntries /> </cffunction>
Here we are using optional arguments, defined using <cfargument>
tags, to dynamically change our SQL statement each time the method is invoked. The filterByMemberId
argument is checked within the query; if it differs from the default, an additional WHERE
clause is applied to our SQL statement. The maxEntries
argument, on the other hand, is always applied to the maxRows
attribute of the <cfquery>
tag, but with a very large default value.
在这里,我们使用可选的参数(使用<cfargument>
标记定义)在每次调用方法时动态更改SQL语句。 在查询中检查filterByMemberId
参数; 如果它与默认值不同,则将附加的WHERE
子句应用于我们SQL语句。 另一方面, maxEntries
参数始终应用于<cfquery>
标记的maxRows
属性,但是具有非常大的默认值。
To call the function from our member profile page (profile.cfm
), we would use the following syntax for <cfinvoke>
:
要从成员个人资料页面( profile.cfm
)调用该函数,我们将对<cfinvoke>
使用以下语法:
<cfinvoke component="bookblogs.components.BlogManager"
method="getBlogEntries"
returnvariable="theirBlogEntries">
<cfinvokeargument name="filterByMemberId" value="#url.memberId#" />
</cfinvoke>
Notice we are now using a nested tag, <cfinvokeargument>
, to pass the member ID to the filterByMemberId
argument of our function. Similarly, on our homepage (index.cfm
) we now invoke the component function using the maxEntries
argument to limit the results returned:
注意,我们现在使用一个嵌套标记<cfinvokeargument>
,将成员ID传递给函数的filterByMemberId
参数。 同样,在我们的首页( index.cfm
)上,我们现在使用maxEntries
参数调用组件函数以限制返回的结果:
<cfinvoke component="bookblogs.components.BlogManager"
method="getBlogEntries"
returnvariable="recentBlogEntries">
<cfinvokeargument name="maxEntries"
value="#application.numberOfBlogEntriesOnHomePage#" />
</cfinvoke>
If neither argument is provided, the function still behaves as it originally did, which is suitable for use on the blog entry listing page.
如果未提供任何参数,则该函数的行为仍与原始情况相同,适合在博客条目列表页面上使用。
NOTE: Security Considerations Earlier in the article I mentioned the access attribute that appears on the <cffunction>
tag. This attribute controls where our CFC can be invoked from. ColdFusion allows every function in a component to individually set this attribute to one of four different values explained below:
注意:安全注意事项在本文前面,我提到了<cffunction>
标记上显示的access属性。 此属性控制可从何处调用我们的CFC。 ColdFusion允许组件中的每个函数分别将此属性设置为以下说明的四个不同值之一:
Private
: the function can only be run from within the component.Private
:该功能只能在组件内部运行。Package
: the function can only be run from within the component or from other components in the same folder.Package
:该功能只能从组件内部或同一文件夹中的其他组件运行。Public
: the function can run from any template or component on the server. This is the default.Public
:该功能可以从服务器上的任何模板或组件运行。 这是默认值。Remote
: the function can be accessed directly from external processes, including Ajax scripts, web service requests, Flex and Flash remoting, and even directly in the address bar of the browser.Remote
:可以直接从外部进程访问此功能,包括Ajax脚本,Web服务请求,Flex和Flash远程处理,甚至可以直接在浏览器的地址栏中访问。
As a general rule, you should always set the level of access to the lowest possible value that meets your requirements.
通常,应始终将访问级别设置为满足要求的最低值。
完成BlogManager
(Completing BlogManager
)
At this point the advantages of consolidating our business and data access logic in a single component should start to become clear. Any changes to the underlying data or business rules can be effectively hidden from the rest of the application. If we were asked to filter out unapproved blog entries from all pages, for example, we would simply change the SQL of the getBlogEntries
function. Likewise, if we decided to incorporate news feeds from independent book-related blogs using RSS, the change could be made without affecting the other application pages.
在这一点上,将我们的业务和数据访问逻辑整合到一个组件中的优势应该开始变得清晰起来。 对基础数据或业务规则的任何更改都可以有效地对应用程序的其余部分隐藏。 例如,如果要求我们从所有页面中过滤出未经批准的博客条目,则只需更改getBlogEntries
函数SQL。 同样,如果我们决定使用RSS将来自独立书籍相关博客的新闻提要合并,则可以在不影响其他应用程序页面的情况下进行更改。
To complete the BlogManager
component we need to add methods to create, read, and update blog entries. We also need functions to add comments to blog entries and work with the list of available blog categories.
为了完成BlogManager
组件,我们需要添加创建,读取和更新博客条目的方法。 我们还需要用于向博客条目添加评论并使用可用博客类别列表的功能。
The BookBlogs site contains pages devoted to books, authors, and member information. Each of these sets of information have their own business and data access logic that can benefit from being encapsulated into ColdFusion components such as BookManager
and MemberManager
.
BookBlogs站点包含专门介绍书籍,作者和会员信息的页面。 这些信息中的每一套都有自己的业务和数据访问逻辑,这些逻辑可以通过封装到ColdFusion组件(例如BookManager
和MemberManager
。
The entire site, including a completed version of BlogManager
, BookManager
, MemberManager
, and other ColdFusion components can be found within the source code download. The source code also has additional hints and tips included as comments.
整个站点,包括BlogManager
, BookManager
, MemberManager
以及其他ColdFusion组件的完整版本,都可以在源代码下载中找到 。 源代码还包含其他提示和技巧作为注释。
So far we have centralized our business logic and data access throughout our application, and probably saved ourselves countless hours in its future support — but now it’s time to think even bigger!
到目前为止,我们已经在整个应用程序中集中了业务逻辑和数据访问权限,并可能在未来的支持中节省了无数小时-但现在是时候考虑更大了!
使用氟氯化碳做更多的事情 (Do More with CFCs)
In addition to the advantages we have already explored, the highly structured nature of CFCs allows ColdFusion to integrate very tightly with the CFC definitions within applications to provide impressive capabilities with little effort.
除了我们已经探究的优势之外,CFC的高度结构化性质使ColdFusion可以与应用程序中的CFC定义紧密集成,从而毫不费力地提供令人印象深刻的功能。
Using CFCs we can:
使用CFC,我们可以:
automatically publish web services by changing the access level of a function to
remote
通过将功能的访问级别更改为
remote
来自动发布Web服务- bind rich Ajax controls directly to our CFCs 将丰富的Ajax控件直接绑定到我们的CFC
respond to events like application start, session start, and even missing templates by using an
application.cfc
file通过使用
application.cfc
文件来响应诸如应用程序启动,会话启动甚至丢失的模板之类的事件- design applications that communicate with external services and agents such as JMS, SMS, Flex Messaging, and Flash Remoting 设计与外部服务和代理(例如JMS,SMS,Flex Messaging和Flash Remoting)进行通信的应用程序
- effectively use community CFC-based frameworks that automate database code and more 有效使用基于社区CFC的框架来自动化数据库代码等
Covering even the basics of these topics would take several more articles!
甚至涵盖这些主题的基础知识都需要多篇文章!
使用CFC的提示 (Tips for Using CFCs)
ColdFusion components are easy to implement and use. Perhaps the toughest part is deciding how, where, and when to use components within your applications. This article has showcased a very narrow usage of CFCs within your applications, but there are no hard and fast rules. Below are my own personal tips on how to use CFCs effectively:
ColdFusion组件易于实现和使用。 也许最困难的部分是确定如何,在何时何地使用应用程序中的组件。 本文展示了您的应用程序中CFC的使用范围非常狭窄,但是没有硬性规定。 以下是我自己有关如何有效使用CFC的个人提示:
- Other forms of reuse, such as page templates, custom tags, and individual UDFs still have their uses. Where CFCs really shine is in capturing specific business rules and data access logic. Custom Tags and UDFs, on the other hand, are ideal for generic output and data manipulation tasks that aren’t specific to any business need. 其他重用形式,例如页面模板,自定义标签和单个UDF,仍然有其用途。 CFC真正发挥作用的地方在于捕获特定的业务规则和数据访问逻辑。 另一方面,自定义标签和UDF非常适合并非特定于任何业务需求的通用输出和数据处理任务。
- Organizing CFCs around independent related data and functionality is important. Giving your CFCs names that reflect concrete objects, well-defined business concepts, and even job titles can help keep CFCs focused on their set of responsibilities. 围绕独立的相关数据和功能组织CFC非常重要。 提供反映具体对象,定义明确的业务概念甚至职位的CFC名称,可以使CFC专注于其职责集。
Document your CFCs using the hint attribute on both
<cfcomponent>
and<cffunction>
tags. These hints, although optional, are useful for both reviewing source code manually and through the component explorer. Documentation is important when others must work with your code or when you’ll need to be able to understand it after development.使用
<cfcomponent>
和<cffunction>
标记上的hint属性记录您的CFC。 这些提示(尽管是可选的)对于手动检查源代码和通过组件资源管理器都有用。 当其他人必须使用您的代码或在开发后需要能够理解它时,文档很重要。- Learn more. ColdFusion components are your gateway into both a better understanding of object oriented programing and the ability to utilize the most powerful features of ColdFusion. 学到更多。 ColdFusion组件是您更好地了解面向对象编程以及利用ColdFusion最强大功能的能力的门户。
从这往哪儿走 (Where to Go from Here)
I recommend the following resources for learning more about ColdFusion components:
我建议使用以下资源来了解有关ColdFusion组件的更多信息:
Adobe ColdFusion CFML Language Reference, Developer’s Guide, and general documentation
Adobe ColdFusion Developer Center, ColdFusion components area
结论 (Conclusion)
During this article we’ve discovered what ColdFusion components are, how they are defined, and how other pages can be designed to use them. While this is enough to get you started, we’ve barely scratched the surface of what CFCs are capable of!
在本文中,我们发现了ColdFusion组件是什么,如何定义它们,以及如何设计其他页面来使用它们。 虽然这足以让您入门,但我们几乎没有涉及CFC的功能!
Ultimately, CFCs help ColdFusion developers write maintainable and flexible applications that can grow and evolve over time. Even better, they save you work right away through code reuse, and later, through using the advanced features of ColdFusion such as Ajax controls and web service generation. You’ll thank yourself for taking the time to get to know them!
最终,CFC可以帮助ColdFusion开发人员编写可维护的灵活应用程序,这些应用程序会随着时间的推移而增长和发展。 更好的是,它们可以通过代码重用立即保存您的工作,以后再通过使用ColdFusion的高级功能(例如Ajax控件和Web服务生成)来节省您的工作。 您将感谢您抽出宝贵的时间来认识他们!
Remember you can download the complete code archive for the examples presented in this article.
coldfusion