I'm a bit late in finishing up the next part of my Transfer series (I blame Fable 2 - it kept me up till 2AM!), but if you remember the last entry, I discussed how to create, update (save), delete, and get data using Transfer. I also showed how Transfer creates a CFC based on the XML definition we created for our Employees. This is really everything we need to build a simple employee editor, except for one piece - getting a list of employees.
I alluded to the fact that Transfer had many ways of getting data. Yesterday's post showed the simple get() method. Today we will look at list() and it's variants. The list() method takes a class (the name of our data type) and an optional column to sort by. You can also pass a third argument that specifies if the sort should be an ascending sort or a descending sort. This one tends to trip me up. Instead of passing "asc" or "desc", you pass a true or false. True implies ascending and false means descending. (There is a four argument as well but we won't worry about that now.) So all in all, to get a list of employees it takes all of one call.2 <cfset employee = application.transfer.get("employee", url.delete)>
3 <cfset application.transfer.delete(employee)>
4 </cfif>
5
6 <cfset employees = application.transfer.list("employee", "lastname")>
7
8
9 <h2>Employees</h2>
10
11 <cfif employees.recordCount>
12 <table border="1">
13 <tr>
14 <th>Name</th>
15 <th>Email</th>
16 <th> </th>
17 </tr>
18 <cfoutput query="employees">
19 <tr>
20 <td><a href="employee.cfm?id=#id#">#lastname#, #firstname#</a></td>
21 <td>#email#</td>
22 <td><a href="employees.cfm?delete=#id#">Delete</a></td>
23 </tr>
24 </cfoutput>
25 </table>
26 <cfelse>
27 <p>
28 There are no employees now.
29 </p>
30 </cfif>
31
32 <p>
33 <a href="employee.cfm">Add Employee</a>
34 </p>
2
3 <cfif url.id is 0>
4 <cfset employee = application.transfer.new("employee")>
5 <cfelse>
6 <cfset employee = application.transfer.get("employee", url.id)>
7 </cfif>
8
9 <!--- param values --->
10 <cfparam name="form.firstname" default="#employee.getFirstName()#">
11 <cfparam name="form.lastname" default="#employee.getLastName()#">
12 <cfparam name="form.dob" default="#employee.getDOB()#">
13 <cfparam name="form.email" default="#employee.getEmail()#">
14 <cfparam name="form.phone" default="#employee.getPhone()#">
15
16 <cfif structKeyExists(form, "save")>
17 <cfset employee.setFirstName(form.firstname)>
18 <cfset employee.setLastName(form.lastname)>
19 <cfset employee.setDOB(form.dob)>
20 <cfset employee.setEmail(form.email)>
21 <cfset employee.setPhone(form.phone)>
22 <cfset application.transfer.save(employee)>
23 <cflocation url="employees.cfm" addtoken="false">
24 </cfif>
25
26 <h2>Edit Employee</h2>
27
28 <cfoutput>
29 <form action="employee.cfm?id=#url.id#" method="post">
30 <table>
31 <tr>
32 <td>First Name:</td>
33 <td><input type="text" name="firstname" value="#form.firstname#"></td>
34 </tr>
35 <tr>
36 <td>Last Name:</td>
37 <td><input type="text" name="lastname" value="#form.lastname#"></td>
38 </tr>
39 <tr>
40 <td>Date of Birth:</td>
41 <cfif isDate(form.dob)>
42 <cfset v = dateFormat(form.dob)>
43 <cfelse>
44 <cfset v = "">
45 </cfif>
46 <td><input type="text" name="dob" value="#v#"></td>
47 </tr>
48 <tr>
49 <td>Email:</td>
50 <td><input type="text" name="email" value="#form.email#"></td>
51 </tr>
52 <tr>
53 <td>Phone:</td>
54 <td><input type="text" name="phone" value="#form.phone#"></td>
55 </tr>
56 <tr>
57 <td> </td>
58 <td><input type="submit" name="save" value="Save"></td>
59 </tr>
60 </table>
61 </form>
62 </cfoutput>
Comment 1 written by Tim Garver on 6 November 2008, at 9:32 PM
Comment 2 written by Sean on 6 November 2008, at 9:32 PM
Comment 3 written by Raymond Camden on 6 November 2008, at 9:35 PM
Comment 4 written by Bob Silverberg on 6 November 2008, at 10:37 PM
Transfer has no way of knowing that 0 is not a valid id, so it will query the database to find out. By using transfer.new() whenever you know that you want an empty object you can avoid that database access, which seems like it would save more overhead than a simple cfif.
Comment 5 written by Sean on 7 November 2008, at 5:48 AM
Comment 6 written by Bob Silverberg on 7 November 2008, at 8:16 AM
I was talking specifically about using get() vs. new() when creating a Transfer Object. If you run a quick test I believe you'll find that any time you call transfer.get("myclass",0) it will run a query against your database to see if 0 is a real record. Even if you do this several times within a single request (e.g., if you want to create multiple Line Items for an Order), if you use transfer.get() instead of transfer.new() it will run a query against the database each and every time.
Note that my use of 0 in the above example is just an example of a value that does not correspond to a valid record. There is nothing magical about 0 - if you do have a record in your table with an id of 0 it would simply retrieve that record, which is yet another reason to use transfer.new() instead of transfer.get() if you know you want an empty Transfer Object.
Comment 7 written by Sean on 7 November 2008, at 12:17 PM
Comment 8 written by Tim Garver on 7 November 2008, at 1:41 PM
Found a few issues I can't seem to work around.
Lets say you have an existing query you want to replace with a Transfer object.
In the query you have several Expressions in the select list as column aliases.
[code] select N.start_time + 5/24 + N.GMT_OFFSET/24 as ST,
N.* FROM table N where N.x=y
[/code]
How can this be accomplished via Transfer?
I have tried to make a property default but thats not allowed in the transfer.xml object.
Anybody have any ideas?
Great work Ray!!
Tim
Comment 9 written by Raymond Camden on 7 November 2008, at 1:44 PM
I'm not sure when I'll cover it in this series. I'm kinda playing things out on the fly. The plan now is:
Joins (2-3 blog entries on relating data)
Getting Data (more advanced then get/list, TQL)
Decorators
Events
Conclusion
So as you can see, it may be late next week until I hit it up, and MAX will definitely slow me down.
Comment 10 written by Tim Garver on 7 November 2008, at 1:58 PM
i have a few of those now, but they are the basic ones my CFC Generator built for me which just has validation in them.
I tried TQL but it doesn't support
Aggregate functions
SQL Functions
Subselect in FROM statements.
Subselect in SELECT Column statements.
Still loving Transfer...
Tim
Comment 11 written by Henry Ho on 7 November 2008, at 5:45 PM
http://www.quackfuzed.com/index.cfm/2008/11/7/Code...
[Add Comment] [Subscribe to Comments]