ColdFusion 9 Developer Tutorial
John Farrar
Chapter No.4 "ORM Database Interaction"
In this package, you will find: A Biography of the author of the book A preview chapter from the book, Chapter NO.4 "ORM Database Interaction" A synopsis of the book’s content Information on where to buy this book
About the Author John Farrar is a seasoned developer and business owner whose company specializes in web-based solutions. His love for design and solving problems has inspired successful customer projects to a number of open source solutions growing in popularity. He has learned ColdFusion, SQL, CSS/web design, AJAX, and other technologies to help fulfill the customer’s technical needs. Yet he is more about the business needs and goals than finding a way to use technology for the sake of technology. That is why he uses the handle and company name “SOSensible”. Best practices are great guides but they change over time. John tries to implement and extend best practices to respond to project goals. His focus is to create solutions that are accessible, duplicatable, and sustainable which he calls ADS for short. Some examples of his ADS compliant efforts are his SOS, COOP, and CFish projects. SOS is an application framework that embraces the personality of the developer. This lets them build applications to run on the same site but in the style they like to code. COOP is covered in this book and splits the code that looks more like an obstacle course into separate pages covering page design and business intelligence in cooperative but separate packages. CFish is his latest focus where he is seeking to bring universal web skinning to ColdFusion developers. All of these are focused on increasing functional accessibility,
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
duplicatable reuse, and sustainable results. Best practices are great but John believes we can do better than that. These principles and his open attitude have given him many opportunities. He has done work for Brunswick Recreation, Sprint, Apple, and Blue Cross in the enterprise realm. This knowledge has inspired and prepared him to also remember the roots of his childhood where his father was a small business owner. Realizing that small businesses make up over 90 percent of the market, he seeks to extend the practice beyond the enterprise boarders. He has also contributed to several other community projects and enjoyed speaking at national developer conventions over the years. You can follow him on his blog at http://www.sosensible.com/index.cfm/blog or at @sosensible on twitter.
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ColdFusion 9 Developer Tutorial Adobe ColdFusion is an application server, renowned for rapid development of dynamic websites, with a straightforward language (CFML), powerful methods for packaging and reusing your code, and AJAX support that will get developers deep into powerful web applications quickly. However, developing rich and robust web applications can be a real challenge as it involves multiple processes. With this practical guide, you will learn how to build professional ColdFusion applications. Packed with example code, and written in a friendly, easy-to-read style, this book is just what you need if you are serious about ColdFusion. This book will give you a clear, concise, and, of course, practical guidance to take you from the basics of ColdFusion 9 to the skills that will make you a ColdFusion developer to be reckoned with. ColdFusion expert John Farrar will teach you the basics of ColdFusion programming, basic application architecture, object reuse, and ORM concepts before showing you a range of topics including AJAX library integration, RESTful Web Services, Unit Testing, building custom tags, and his hybrid example of tags and objects COOP. All these together will make you the toast of your ColdFusion developer town. This book digs deep into the basics, with real-world examples of the hows and whys, to get more done faster with ColdFusion 9. This book's website (http://www.sosensible.com/index.cfm/books/) also covers the new features of ColdFusion Builder and additional version 9 updates.
What This Book Covers Chapter 1, Web Pages—Static to Dynamic is a fast track introduction to what makes CF better than HTML and how to program with CFML. Chapter 2, Basic CFCs and Database Interaction which makes our code easier to support is done by packaging logic into reusable containers. This chapter will introduce you to CFML-based object coding. Chapter 3, Power CFCs and Web Forms is a chapter that shows the power you can achieve by packaging things into CFCs. Their features are faster coding, easier support, and simpler to read code with a minor up-front investment.
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4, ORM Database Interaction talks about the Object Relation Management (ORM) standard in CF9. This is a built in object technology that works with your database without creating SQL specific to each database platform. Chapter 5, Application, Session, and Request Scope is a chapter that teaches us how controlled sharing will speed up your application and make them easier to build and understand. Chapter 6, Authentication and Permissions shows us how to manage who can and who cannot do things. Chapter 7, CFScript in CF9 is the first fully-featured script for CFML. This chapter will help us get familiarized with script and shows how to enjoy its new completeness. Chapter 8, CF AJAX User Interface covers the tag-based language in CFML that lets us interact with AJAX in ways we can only appreciate. This chapter covers the UI element features in ColdFusion. Chapter 9, CF AJAX Forms covers how ColdFusion lets us build richer forms with the power of built-in tags. Chapter 10, CF AJAX Programming will teach us how to work in the browser when we want to use JavaScript to interact with the code. This chapter covers the common interface and how to use it. Chapter 11, Introduction to Custom Tags shows us how to take advantage of tag-based packaging and how to do it when we desire. Chapter 12, ColdFusion Powered Views will introduce us to a view tag library that makes forms and view code easier and much simpler to support. Chapter 13, Control Logic Processing shows us how to interact with the events and view elements from a request controller. This chapter helps us understand a methodology of coding that makes for a logical flow of code where things fit in smartly. Chapter 14, Guide to Unit Testing covers a growing and very beneficial concept of software development and sustainability—unit testing. Appendix A, Beyond this Book is based on some additional thoughts from the author. This is a tutorial book and it made sense for me to put in a chapter that shares thoughts about moving beyond the reach of a single book introduction to web development. Appendix B, Tools and Resources lists some of the tools we use at my company and thoughts on each of them. The number of tools and resources has grown in volume to the point where half of this book would cover this topic alone.
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction In this chapter, we will learn about ORM, the Object Relational Management feature of ColdFusion 9. This is one of the new features that many developers have declared to be the number one reason for them to upgrade. We can still write SQL code to interact with our database but in many cases this will not be the preferred method. The new ORM interface in ColdFusion is so simple and powerful that beginners to gurus will choose the ORM option for data interaction. Many developers who have never moved beyond just using the query tag are for the first time enjoying a new interface to their data persistence. Here is what this chapter will cover: •
Introduction to ORM in ColdFusion
•
Simple guide to mapping data
•
Working with data through object entities
•
Working with relational data
•
Adding custom configuration
Introduction to ORM in ColdFusion Traditionally in ColdFusion we have used <cfquery/> to hold SQL code that interacts with our data for inserting, updating, and returning one or more records back from our data stores. At best, most developers find this process to be redundant for simple functions. We will be looking at a new paradigm where our code that interacts with databases is easier to write, easier to update, and in some cases, more featured.
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
A side benefit to using ORM that most have not considered is that it makes code more portable. If you want to share code you write or code that others write in your applications, one of the historical obstacles would be making sure they were using the same SQL platform as you. ColdFusion 9 has put a superb interface on a technology created for the Java world called Hibernate. In the same style that working with <cfquery/> has kept data interaction simple, this interface is somewhat like data technology 2.0 for ColdFusion developers. We still have the simple power but also have second generation features that will take us far into the future. So if you take an application built with Oracle via ColdFusion ORM, you can use the same basic application on a server running MySQL, MSSQL, or even Derby. Of course you will also be able to customize it for specific SQL platforms to run special features if desired.
ORM-enabled application configuration The first thing we need to do is create an Application.cfc file with the minimal requirements of configuration. We must include two settings for the ORM to work. We must include the ormenabled and the datasource variables in our Application.cfc file. We will also use one of the default databases (cfartgallery) that came installed with the ColdFusion server: <cfcomponent> <cfscript> this.name = "CF9DT_ch4"; this.ormenabled = TRUE; this.datasource = "cfartgallery"; </cfscript> </cfcomponent>
Application.cfc is never meant to be run on its own, so do not expect this code to run by calling it direcly.
We can see that things are simple so far. We will continue to focus on what it takes to replace the basic functionality we have been using in the previous versions of ColdFusion. Yet, we need to remember that none of that functionality has been removed. The ORM technology is only an alternative way to manage data for those who want to use newer, fancier features.
[ 90 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4
Next we need to create a CFC which uses a technique called a "mapping". There is a table in the database called art. We will use that table for our first example. We will have three files when we test the code: •
Application.cfc
•
(ORM) CFC for the table(s) we interact with
•
Page (a .cfm file) where the CFC will be used
ORM-enabled CFCs Let's now look at creating our ORM CFC. The first thing we need is to set up our CFC so it knows it is an ORM-based data object. We need to set some attributes for our main component tag. The first is the persistent attribute. This tells ColdFusion and Hibernate to persist this object mapping. The next is the table attribute where we declare the table that our object will be representing. This may be hard to believe but if we want to ignore relations and other details, we could use this ORM object with no additional changes. Save the following code to a file called ART.cfc for our first object. If you want you can use the one in the Chapter 4 directory of the sample code: <cfcomponent persistent="true" table="ART"> </cfcomponent>
Now we can create our page to use the ORM object. Our first objective is to create an object based on the ART.cfc ORM file. We will see that these are referred to as "entity" objects. We will simply call this object ART because ColdFusion 9 knows how to find the database entity object that matches. One of the amazing aspects of this new technology is all the things that happen without writing code to make them happen. This example will show how we can connect to the database through the entity and return the current number of rows. Now this is seen as an array of structures from the perspective of how ColdFusion sees the entity data. We will loop over the data and output each item to the browser screen. We use the data entity (each item) as an array object and pass the array item followed by a getter, returning an item value, using the field name. So to get the table field artName, we use getArtName() and it returns the value for that row in the database: <cfset data = entityLoad("art")> <cfoutput> <cfloop from="1" to="#arrayLen(data)#" index="iRow"> Art : #data[iRow].getArtName()#<br/> </cfloop> </cfoutput>
[ 91 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
We cannot make it easier to work with data than this. We will do some things that are not that easy as the chapter progresses, but first let's run this page and see what we get:
Now that is easy enough for about anyone to pull and place data on the page. Let's take a look at what the code would look like if we put in the description for each field of data. Before we do that let's also add one line of code, just for testing, in our Application.cfc file. The ormsettings is a structure that can do many powerful things for us. We should not leave this line on a live server, but this is good for testing because it makes sure our data ORM object is loaded fresh on each server request. <cfcomponent> <cfscript> this.name = "CF9DT_ch4"; this.ormenabled = TRUE; this.datasource = "cfartgallery"; this.ormsettings = {autorebuild="true"}; </cfscript> </cfcomponent>
Application.cfc is never meant to be run on its own, so do not expect this code to run by calling it directly.
[ 92 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4
Now here is the code we would have if we provided a more detailed description about each field in our ART table: <cfcomponent persistent="true" table="ART"> <cfproperty name="ARTID" ormtype="int" fieldtype="id" /> <cfproperty name="ARTISTID" ormtype="int" /> <cfproperty name="ARTNAME" ormtype="string" /> <cfproperty name="DESCRIPTION" ormtype="clob" /> <cfproperty name="PRICE" ormtype="double" /> <cfproperty name="LARGEIMAGE" ormtype="string" /> <cfproperty name="MEDIAID" ormtype="int" /> <cfproperty name="ISSOLD" ormtype="short" /> </cfcomponent>
We have a name that can be but does not have to be the same as the actual field name in the database table. The column name must match the name of the data table field unless you want to add the column attribute with the correct name of that field. We actually do not need to list the ormtype attribute, but we did it here to show the universal data types used by the Hibernate ORM interface. One very important thing to note is that our primary key should be set with a fieldtype attribute having an ID value. We could also set a generator type containing any of the following values: increment, identity, sequence, sequence-identity, seqhilo, uuid, guid, native, assigned, select, foreign. Until we gain more experience, it is good to use the default of assigned.
Understanding entities When we used queries we would refer to the results of the query by the query name and the field name separated by a dot. So it would be art.artname to retrieve the value for a row. Now if we are using an individual item with ORM, we would use art.getartname() to accomplish the same results. With a query we could not change the values and save them back. This is one of the differences between ORM and query-based data interaction. Now we can use the same results to update the records in the database. We will look at that in just a moment, but first let's look at pulling a single record back from the database rather than an array/ collection of records: <cfscript> art = entityLoad("art"); piece = entityLoadByPK("art",4); </cfscript> <cfoutput> Art : <br>
[ 93 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction (piece) = #piece.getArtName()#<br> (art[4]) = #art[4].getArtName()#<br> </cfoutput>
Here we are pulling a particular item using the primary key for the piece entity. The art is a collection of entities stored in an array. We can see in the output segment of our code that we pull the same results. This tells us we can approach this in multiple ways and it is equally functional. Here is the output when sent to a browser:
What if we want to change the value of a record stored in the database? How do we modify the value using ORM entities? We use setters which are work coded in the same manner as our getters. If an entity already exists, then we are modifying the existing record. We will modify our previous example to show that we will not only be able to change the value of a record stored in the database, but also be able to modify the value using ORM entities at the same time. ColdFusion with the ORM technology sees that both of these are methods talking about the same entity object. We will add the following lines to our code: <cfscript> art = entityLoad("art"); piece = entityLoadByPK("art",4); </cfscript> <cfoutput> Art : <br> (piece) = #piece.getArtName()#<br> (art[4]) = #art[4].getArtName()#<br> <hr> <cfset piece.setArtName("PAULO_updated")> (piece) = #piece.getArtName()#<br> (art[4]) = #art[4].getArtName()#<br> </cfoutput>
[ 94 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4
We can see that the entity piece has been modified with the setArtName() method. Yet both the piece and the fourth item in the array are updated because they refer to the same entity or record in the database. ColdFusion manages this for us under the hood and keeps things simple. Caution: Be sure you have the correct variable identified when modifying variables. We just happen to have the same array position for item four as we do for the record's primary key in the database. So be careful not to take the wrong concept from the code. Typically the array position of the entity returned in a collection will not match the primary key ID. We just got lucky. Luck is not a good way to code:
Working with entity-object relationships Now we will look at relational connections via our ORM-mapped objects. We need to do this to create a new record in the ART table. The art record has two relationships. It has an artist and a media type. We will find that working with relationships can also be simpler than writing out query relationships. It also has the advantage of being portable from one platform to the next. The field detail added in previously was done to make the ORM relations easier to follow as we read the code. It was just a little extra detail to give more meaning to the relational properties. Add the following code just above the closing <cfcomponent> tag. We will create the two ORM relations and then go back and create the related ORM object CFCs: <!--- Relations ---> <cfproperty name="ARTISTS" singularname="ARTIST" fieldtype="many-to-one" cfc="ARTIST" fkcolumn="ARTISTID"/> <cfproperty name="MEDIA" singularname="MEDIA" fieldtype="many-to-one" cfc="MEDIA" fkcolumn="MEDIAID"/>
[ 95 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
We can see that fieldtype is different here. We also see the type many-to-one. The first item "many" refers to this ORM object. The second item "one" refers to the related object. So the relation states that there can be many objects related to one of the objects listed in the CFC attribute. We also see that there is a foreign key column attribute, fkcolumn, containing the field holding the relational value. We could get an error running the code, so for best practice we will tell the entity not to directly update the artist or media ID fields. The following is the correct way to do this via ORM: <cfproperty name="ARTISTID" ormtype="int" insert="false" update="false" /> <cfproperty name="MEDIAID" ormtype="int" insert="false" update="false" />
We can see both of these properties with insert and update attributes set to false. These are the fields listed in the fkcolumn attribute of both the relations. Now we have a richer entity ready to do more for us. We will need to create the two ORM objects before testing it out. We will create an ARTISTS and MEDIA entity object. Here is the code for the ARTISTS table: <cfcomponent persistent="true" table="ARTISTS"> <!---- properties ----> <cfproperty name="ARTISTID" ormtype="int" fieldtype="id" <cfproperty name="FIRSTNAME" ormtype="string" /> <cfproperty name="LASTNAME" ormtype="string" /> <cfproperty name="ADDRESS" ormtype="string" /> <cfproperty name="CITY" ormtype="string" /> <cfproperty name="STATE" ormtype="string" /> <cfproperty name="POSTALCODE" ormtype="string" /> <cfproperty name="EMAIL" ormtype="string" /> <cfproperty name="PHONE" ormtype="string" /> <cfproperty name="FAX" ormtype="string" /> <cfproperty name="THEPASSWORD" ormtype="string" /> </cfcomponent>
/>
Here is the code for the MEDIA table: <cfcomponent persistent="true" table="MEDIA"> <!---- properties ----> <cfproperty name="MEDIAID" ormtype="int" fieldtype="id" <cfproperty name="MEDIATYPE" ormtype="string" /> </cfcomponent>
[ 96 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
/>
Chapter 4
Now if we put a line at the bottom of our last page and dump the entity named piece, the following record would appear on the screen. We notice that in the dump ColdFusion shows us the values directly. We should use the setter and getter methods to interact with these values in our code. If you expand the methods, you will find a setter and getter for each field in the entity. In our updated object, we will also see a couple of new methods such as hasArtists(), hasMedia(), getArtists(), setArtists(), getMedia(), and setMedia(). The has function of course returns a Boolean result. The new relational getters and setters return an array of entities in the same return type as the results of our entityLoad() method. Obviously, the return collection is narrowed, but the results come back in the same type as an array of entities.
[ 97 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
Now we have achieved looking up a record for an art item, and the related artist and media type. We need to understand how to work with this entity object through code. Let's reverse the relationship in the media class before we write the entity code. Here is the correct way to relate the media back to the art works. Add the following code to the end of the MEDIA.cfc object class. We will do one thing different than before. We will set the field type as one-to-many because the relation based on this entity is the reverse of the previous examples. We always name this using the reference of the current object. <cfproperty name="works" cfc="ART" fkcolumn="MEDIAID" fieldtype="one-to-many" >
If we immediately ran the previous piece of code, we would get too much information. There is a simple way to prevent getting too much information in ColdFusion. We add one attribute to our dump tags. In this case, two levels of information and/or rows of array data are sufficient. So just write top="2" inside the CFDump tag and we would get the following result for the media section of the data dump:
There are actually more than two rows but this attribute helps keep the amount of information under control. If this were large enterprise data, the reasons for doing this would become obvious. So we should remember to use the top attribute which of course could be set to 10, 20, or any number you prefer. What is neat is how it links back to the art-related records. This means the entity objects are very smart with little coding. Just a few lines of mapping description tags, and our data tools become very powerful. So how do we create the code needed to output this related information? We will not only output the related information, but we will make sure to pull a single record returned without the array of entities in the same example: <cfscript> art = entityLoad("art",3,true); artist = art.getArtist(); media = art.getMedia(); [ 98 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4 </cfscript> <cfdump var="#media#" top="2">
This code block will give us the same basic results as the nested media entity previously shown, except of course it will not be nested. We see that just like the methods added for the attributes, we now have methods added for the entity items. So in the place where we would code getArtID() to return the artID field from the art table record, we are now going to code getMedia() to return the entity item. Looking at the code you will notice that we show how to return both the artist and the media. You should also note that we coded our entity load in a different manner this time. We passed in the table, primary ID key, and the value of true. This is used when we want it to return the actual single entity without the array structure. We will only show the dump for the media in this example. Also remember there are more than two records for art works. We limited that with the top attribute in CFDump. The last thing we should notice is the works rather than the ART property/ entity type. This is because we gave the relationship in the MEDIA.cfc an attribute name of works. This shows we have naming flexibility that can make our code more abstract as desired.
[ 99 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
Many-to-many relationships The next thing we will look at is setting up many-to-many type relations. These relationships are where one table is connected to another table by a link table. The link table contains a link field for both the source and the target tables. We will set the link from the orders table to the items table. This will create the ability to look at an order and see the items that are on an order using ORM to make things easier to code. Traditionally we would write a query in the CFQuery tag that did a double-level join. Here we will use a property tag with the fieldtype attribute set to many-to-many: <cfproperty name="item" fieldtype="many-to-many" cfc="ART" fkcolumn="ORDERID" linkTable="ORDERITEMS" inverseJoinColumn="ARTID">
The code shown should be added to the ORDERS.cfc table. When setting the details for the mapping, it is always done from the point of view of the current entity class. We can use an alias just as we did previously in this chapter. Here we set the alias name to item to represent an order item. The fkcolumn is the column that exists in the current table and the link table. The inverseJoinColumn is the field that exists both in the linkTable and the target entity table. That is enough to get the connections working. ORM is very powerful and adaptable, but we will go with this simplified ORM class for learning because we just need to see the basics of how it works: <cfscript> order = entityLoad("orders",2,true); </cfscript> <cfdump var="#order#" top="2">
This is the dump that our code outputs:
[ 100 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4
[ 101 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
Here is the property we would place in ART.cfc to build reverse functionality. There are many other attributes that can be added. We can control the order, cascading relationship functionality. A collection can be either a structure or an array. As we can see in the screenshot of the dump, entities use array-based collections by default: <cfproperty name="order" fieldtype="many-to-many" cfc="ORDERS" fkcolumn="ARTID" linkTable="ORDERITEMS" inverseJoinColumn="ORDERID">
Working with relational data Now we should look at using this relational data with forms and learn how to store information. If this mapping technology seems slightly difficult on the front side, then hang on just one moment and you will be surprised to see how much simpler the ORM makes the logic and view parts of your application. The ORM concepts are where your "model" is built. Model is a programming term for the things that you interact with in a program. The technology in this chapter is what we would consider a persistent model. The information is persisted via a database in this use case. We will create the beginnings of a cart page, so we can add an item to the cart. Create an add item page first. Note that this is just for the code example. The way you build a cart should depend on your needs: <cfscript> if(structKeyExists(session,"cartID")){ cart = entityLoadbyPK("ORDERS",session.cartID); } else { cart = entityNew("ORDERS"); cart.setOrderStatus(entityLoad("ORDERSTATUS", {STATUS="pending"},true)); cart.setTax(0); cart.setTotal(0); cart.setCustomerFirstName("CF9DT"); cart.setCustomerLastName("Student"); cart.setCustomerLastName("123 Anywhere St"); cart.setCity("no"); cart.setState("ST"); cart.setPostalCode("0000"); entitySave(cart); session.cartID = cart.getORDERID(); } if(structKeyExists(url,"remove")){ cart.removeItem(entityLoad("ART",url.remove,true)); } if(structKeyExists(url,"buy")){ art = entityLoadByPK("ART",URL.buy); [ 102 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4 if(!cart.hasItem(art)){ cart.addItem(art); } } cart.setOrderDate(now()); entitySave(cart); </cfscript> <cfinclude template="navigation.cfm"/> <cfoutput> <h1>Cart</h1> <table border="1"> <tr> <td>Item</td> <td>Price</td> <td>Remove</td> </tr><cfif isArray(cart.getItem()) AND arrayLen(cart.getItem())> <cfloop array="#cart.getItem()#" index="i"> <tr> <td>#i.getArtName()#</td> <td>#dollarFormat(i.getPrice())#</td> <td><a href="cart.cfm?remove=#i.getArtID()#">Remove</a></td> </tr></cfloop><cfelse> <tr> <td colspan="4">No Items In Cart</td> </tr></cfif> </table> </cfoutput>
Okay, let us walk through that code. One of the first and most important things to note at this time is that we do not persist an entity object in a persistent ColdFusion scopeâ&#x20AC;&#x201D;application or session scope, basically. We are going to follow the rule of checking our session for the ID of our cart stored in the session scope. This will allow us to do the same thing without nasty surprises of data abnormalities. We would also be using forms and more in a full application; however, here we provided just enough detail to show how we would create and manage a shopping cart. This is to illustrate a real-life example of how data could be maintained in tables where there is a many-to-many relationship. We also have logic that allows us to both add and remove items from the cart. For each call to the server in the shopping cart, we update the date and save the cart.
[ 103 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
The last thing for our page is to generate the view. We include a file for navigating through the page. The code for this file is as follows: <div> <span><a href="art_items.cfm">Items for Sale</a></span> &nbsp; <span><a href="cart.cfm">Cart</a></span> </div>
We then create a table for our tabular cart data. Again we could dress up a realworld application in a much nicer way, but we want to focus on code here. There are times when the entity will return null, which ColdFusion sees as an empty string. This is why we wrapped our loop logic with a conditional cfif tag set. We also included an arrayLen() check in the previous Cart display code. If the array is empty or non-existing, it allows us to place alternate information on the screen telling the user that there are no items in the cart at that point. We also need an art_items.cfm page to show what items are still available for sale at this time: <cfscript> art = entityLoad("art",{ISSOLD=false},"ARTNAME"); </cfscript> <cfinclude template="navigation.cfm"/> <cfoutput> <ul><cfloop array="#art#" index="i"> <li> <a href="item.cfm?item=#i.getARTID()#">Preview</a> #i.getARTNAME()# @ #dollarFormat(i.getPRICE())#</li></cfloop> </ul> </cfoutput>
Here we see a special way of using our entityLoad() method. The second argument is a filter. If we don't name the field represented by the filter, it assumes the primary key field. Here we told it to only return items that have not been sold. Next, we see that the art array stores its collection item in the index variable for each iterative loop. We can then use that iterative loop to pull data as we would with the alias being used for the individual art item in this case. Here is the output:
[ 104 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4
Next we need to create our item.cfm page. We are using the entityLoadByPK() method this time. It works the same as if we used entityLoad("ART",URL. item,true). You can use either one as you choose. We include the navigation, as in our cart page. Then we put out our information to the screen. We also include a conditional link of course, to deal with someone who may have bookmarked the page on an item that may have been sold before they return: <cfscript> art = entityLoadByPK("ART",URL.item); </cfscript> <cfinclude template="navigation.cfm"/> <cfoutput> <h1>Item Preview Page</h1>
[ 105 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction <h2>#art.getArtName()#</h2> <div> by #art.getArtist().getFirstName()# #art.getArtist().getLastName()# </div> <div> Media: #art.getMedia().getMediaType()# </div> <div> Price: #dollarFormat(art.getPrice())# </div> <div> <cfif art.getIsSold()><strong>Already Sold</strong> <cfelse> <a href="cart.cfm?buy=#art.getArtID()#">Buy #art.getArtName()# </a> </cfif> </div> </cfoutput>
Here is what the screen would look like if we choose The Lake as our selection:
This shows how amazingly simple code can be, using the new ColdFusion 9 ORM. Now if we click on Buy The Lake, we will get the following view:
[ 106 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Chapter 4
Our sample is now complete. If we return to Items for Sale, the items will be shown as before. If we try to buy the lake again before it is marked, purchasing it will not add it in the cart twice. Of course there is more logic that would be needed in a real-world application because we certainly would not want two people trying to buy a piece of art that sells for $150,000 at the same time. That would be a huge public relations mess. If we add other pieces, they will be shown on the screen. If we click on the Remove link by any of the pieces, they will be properly removed from the cart and from the database. Welcome to the beginning of a very simple shopping experience.
ORM functions There are a number of entity functions that are standard in ColdFusion. There are two basic groups of functions: entity functions and ORM functions. This list is just provided here for information to get a broad-scope view of what functions are provided inside ColdFusion ORM: •
Entity functions are as follows: ° entityDelete ° entityLoad ° entityLoadByExample ° entityLoadByPK ° entityMerge ° entityNew ° entityReload ° entitySave ° entityToQuery [ 107 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
ORM Database Interaction
•
ORM functions are as follows: ° ORMClearSession ° ORMCloseSession ° ORMEvictCollection ° ORMEvictEntity ° ORMEvictQueries ° ORMExecuteQuery ° ORMFlush ° ORMGetSession ° ORMGetSessionFactory ° ORMReload
There is a wonderful ORM-like tool that is great for people getting started called Data Manager. It is an alternative to the ORM features in CF9. If you need an ORM-like library that is backwards compatible with previous versions of ColdFusion, this is a great solution. You can find this library at http://datamgr.riaforge.com. I will be blogging at http://www.sosensible.com on both of these technologies.
Summary We have reduced the size of our page code. Also, if we want to set up a function to edit another table, we can use the techniques that have been discussed in this chapter. We can create a simple data object, and a child object along with a few parameters that we have seen in product.cfc. This is known as Object Relational Management (ORM) to the development community. It is a very simple example to get started with. Now, we can clearly see that when it comes to reuse, this is a much better way to write our code. The following is a summary of our discussion in this chapter: •
Universal data code, platform independent
•
How to set up applications for entity ORM-based CFCs
•
How to create entity ORM-based CFCs
•
How to create relationships for entity ORM-CFCs
•
How to code outside the entity to manage the entity objects
[ 108 ]
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book
Where to buy this book You can buy ColdFusion 9 Developer Tutorial from the Packt Publishing website: https://www.packtpub.com/coldfusion9-developer-tutorial/book. Free shipping to the US, UK, Europe and selected Asian countries. For more information, please read our shipping policy.
Alternatively, you can buy the book from Amazon, BN.com, Computer Manuals and most internet book retailers.
www.PacktPub.com
For More Information: www.PacktPub.com/coldfusion-9-developer-tutorial/book