ColdFusion developers often refer to a file of conceptually related UDFs as a UDF library. Actually, there are no specific rules about what kinds of UDFs you can collect into a library, but it makes sense to group your UDFs into files according to some kind of common concept. In fact, you have already seen a small UDF library: the FilmFunctions1.cfm file shown in Listing 22.2. It contains only one function, but you can still think of it as a library that you could expand to include other film-related functions in the future. Designing the UDF LibraryLet's say your team needs some more film-related functions added to the FilmFunctions library. Sounds like fun! You decide to create a new version of the library file, called FilmFunctions2.cfm. You sit down with the other members of your team, and come up with the list of functions shown in Table 22.4.
Listing 22.4 shows the code for the new FilmFunctions2.cfm UDF library. Listing 22.4. FilmFunctions2.cfm A UDF function library<!--- Filename: FilmFunctions2.cfm Created by: Nate Weiss (NMW) Purpose: Creates a library of user-defined functions related to films ---> <!--- Function: getFilmsQuery() ---> <!--- Returns a query object from the Films table in the database ---> <cffunction name="getFilmsQuery" returntype="query" output="false"> <!--- Optional argument: FilmID ---> <cfargument name="filmID" type="numeric" required="No"> <!--- This variable is for this function's use only ---> <cfset var filmsQuery = ""> <!--- Query the database for information about all films ---> <!--- The query is cached to improve performance ---> <cfquery name="filmsQuery" datasource="ows" cachedwithin="#createTimespan(0,1,0,0)#"> SELECT * FROM Films <!--- If a FilmID argument was provided, select that film only ---> <cfif isDefined("ARGUMENTS.filmID")> WHERE FilmID = #ARGUMENTS.filmID# <!--- Otherwise, get information for all films, in alphabetical order ---> <cfelse> ORDER BY MovieTitle </cfif> </cfquery> <!--- Return the query ---> <cfreturn filmsQuery> </cffunction> <!--- Function: getFilmTitle() ---> <!--- Returns the title of a film, based on FilmID ---> <cffunction name="getFilmTitle" returnType="string" output="false"> <!--- One argument: FilmID ---> <cfargument name="filmID" type="numeric" required="Yes"> <!--- This variable is for this function's use only ---> <cfset var getFilm = ""> <!--- Get a query object of all films in the database ---> <cfset getFilm = getFilmsQuery(ARGUMENTS.filmID)> <!--- Return the film's title ---> <cfreturn getFilm.MovieTitle> </cffunction> <!--- Function: getFilmURL() ---> <!--- Returns the URL to a film's detail page, based on FilmID ---> <cffunction name="getFilmURL" returnType="string" output="false"> <!--- One argument: FilmID ---> <cfargument name="filmID" type="numeric" required="Yes"> <!--- Return the appropriate URL ---> <cfreturn "ShowFilm.cfm?FilmID=#ARGUMENTS.filmID#"> </cffunction> <!--- Include another UDF function library ---> <!--- This one creates the JavaScriptPopupLink() function ---> <cfinclude template="SimpleJavaScriptFunctions.cfm"> <!--- Function: MakeFilmPopupLink() ---> <!--- Returns an HTML link for a film, based on FilmID ---> <cffunction name="MakeFilmPopupLink" returnType="string" output="false"> <!--- One argument: FilmID ---> <cfargument name="filmID" type="numeric" required="Yes"> <!--- Return a link for the film ---> <cfreturn javaScriptPopupLink(getFilmURL(ARGUMENTS.filmID), getFilmTitle(ARGUMENTS.FilmID))> </cffunction> Each of the <cffunction> blocks in Listing 22.4 is fairly simple. It's interesting to note here that UDFs can call other UDFs in the same file. They can even call functions in other files, as long as the <cfinclude> tag has been used to include the other files. NOTE In fact, UDF A can always call UDF B, as long as you've included UDF B in one of the ColdFusion files involved in the page request. It doesn't matter if some of the files are turn included by other files, or deeply the files are included within each other. The order of inclusion doesn't matter either. Let's take a closer look at each one of these new UDFs individually:
Putting the UDF Library to UseListing 22.5 shows a new version of the Film List page (see Listings 22.1 and 22.3 for the previous versions). This version gets its work done with just a few lines of code, and it's more functional, too! Now, when the user clicks a film's title, a small pop-up window displays more information about that film (Figure 22.2). Listing 22.5. FilmList3.cfm Using several UDFs together<!--- Filename: FilmList3.cfm Created by: Nate Weiss (NMW) Purpose: Displays a list of films ---> <!--- Include the set of film-related user-defined functions ---> <cfinclude template="FilmFunctions2.cfm"> <!--- Get a query object about films in database ---> <cfset getFilms = getFilmsQuery()> <html> <head><title>Film List</title></head> <body> <h3>Here is the current list of Orange Whip Studios films:</h3> <!--- Now it is extremely easy to display a list of film links ---> <cfoutput query="getFilms"> #makeFilmPopupLink(getFilms.FilmID)#<br> </cfoutput> </body> </html> First, a <cfinclude> tag is used to include the new library of film-related UDFs. That makes it possible to call the getFilmsQuery() function to get a query object full of information about the films in the company's database. The value returned by the function is assigned to the local getFilms variable. From that point on, the getFilms query object can be used just as if there was an actual <cfquery name="getFilms"> tag on the page. Now it just takes a simple call to makeFilmPopupLink() to create a pop-upenabled link for each film in the getFilms query. Through the magic of the UDF framework, that one line of code looks up the movie's title, obtains the correct URL to display details about the film, and generates the JavaScript code needed to pop up the detail page in a small window. And it's all eminently reusable. Don't user-defined functions rock? |