A while a ago, I posted a discussion about different ways to represent complex data, and a UDF to sort arrays of structures on multiple keys. After reading this post, Brian Fitzgerald asked me if I knew of any UDF that could provide the same kind of functionality for an array of beans (instantiated CFC’s). This made me realize that my blog post had omitted perhaps the most useful way of representing complex data in ColdFusion (version 6 and up): ColdFusion Components!
This is not the place for an in-depth discussion of CFC’s, but if you are interested I can recommend this introduction by Hal Helms. For me, the essential advantage of CFC’s is, that they provide the possibility to encapsulate both data and functionality inside one object(variable). This makes it possible for CFC’s to represent real-life objects more naturally than any other CF datatype. CFC’s also provide great possibilities for writing re-usable and portable code, because they can contain the logic that is necessary to handle the specific data they are holding.
As for Brian’s question, it inspired me to improve my sorting UDF, so that now it is able to sort arrays of objects, the object being either instantiated CFC’s (beans), or structures. The UDF, together with two usage examples, can be downloaded here. The code of the examples is shown below .
<!--- Example: sorting an array of instantiated CFCs --->
<!--- Note: this templates depends on person.cfc being in the same folder --->
<!--- Include UDF template --->
<cfinclude template="sortArrayOfObjects.cfm">
<cfscript>
//EXAMPLE USAGE:
//an array of 4 persons, with three properties...
variables.persons = arrayNew(1);
variables.person = createObject('component','person');
variables.person.setName('Martijn');
variables.person.setAge(29);
variables.person.setWeight(78);
arrayAppend(variables.persons, variables.person);
variables.person = createObject('component','person');
variables.person.setName('Jelle');
variables.person.setAge(29);
variables.person.setWeight(85);
arrayAppend(variables.persons, variables.person);
variables.person = createObject('component','person');
variables.person.setName('Lammert');
variables.person.setAge(51);
variables.person.setWeight(78);
arrayAppend(variables.persons, variables.person);
variables.person = createObject('component','person');
variables.person.setName('Bas');
variables.person.setAge(51);
variables.person.setWeight(78);
arrayAppend(variables.persons, variables.person);
// specify how to sort:
// first on age - descending
// second on weight - ascending
// third on name - ascending
variables.sortkeys = arrayNew(1);
variables.sortKey = structNew();
variables.sortKey.keyName = "age";
variables.sortKey.sortOrder = "descending";
arrayAppend(variables.sortKeys, variables.sortKey);
variables.sortKey = structNew();
variables.sortKey.keyName = "weight";
variables.sortKey.sortOrder = "ascending";
arrayAppend(variables.sortKeys, variables.sortKey);
variables.sortKey = structNew();
variables.sortKey.keyName = "name";
variables.sortKey.sortOrder = "ascending";
arrayAppend(variables.sortKeys, variables.sortKey);
// do the sorting
variables.persons_sorted = sortArrayOfObjects(
arrayToSort = variables.persons,
sortKeys = variables.sortKeys,
doDuplicate = false,
useGetterMethods = true);
</cfscript>
<h3>Unsorted:</h3>
<cfloop from="1" to="#arrayLen(variables.persons)#" index="variables.i">
<cfset variables.person = persons[variables.i]>
<cfoutput>
<p>
Position: #variables.i# <br />
Age: #variables.person.getAge()# <br />
Weight: #variables.person.getWeight()# <br />
Name: #variables.person.getName()# </br>
</p>
</cfoutput>
</cfloop>
<h3>Sorted:</h3>
<cfloop from="1" to="#arrayLen(variables.persons_sorted)#" index="variables.i">
<cfset variables.person = persons_sorted[variables.i]>
<cfoutput>
<p>
Position: #variables.i# <br />
Age: #variables.person.getAge()# <br />
Weight: #variables.person.getWeight()# <br />
Name: #variables.person.getName()# </br>
</p>
</cfoutput>
</cfloop>
<!--- Example: sorting an array of structures --->
<!--- Include UDF template --->
<cfinclude template="sortArrayOfObjects.cfm">
<cfscript>
// EXAMPLE USAGE:
//an array of 4 persons, with three properties...
variables.persons = arrayNew(1);
variables.person = structNew();
variables.person.name = 'Martijn';
variables.person.age = 29;
variables.person.weight = 78;
arrayAppend(variables.persons, variables.person);
variables.person = structNew();
variables.person.name = 'Jelle';
variables.person.age = 29;
variables.person.weight = 85;
arrayAppend(variables.persons, variables.person);
variables.person = structNew();
variables.person.name = 'Lammert';
variables.person.age = 51;
variables.person.weight = 78;
arrayAppend(variables.persons, variables.person);
variables.person = structNew();
variables.person.name = 'Bas';
variables.person.age = 51;
variables.person.weight = 78;
arrayAppend(variables.persons, variables.person);
// specify how to sort:
// first on age - descending
// second on weight - ascending
// third on name - ascending
variables.sortkeys = arrayNew(1);
variables.sortKey = structNew();
variables.sortKey.keyName = "age";
variables.sortKey.sortOrder = "descending";
arrayAppend(variables.sortKeys, variables.sortKey);
variables.sortKey = structNew();
variables.sortKey.keyName = "weight";
variables.sortKey.sortOrder = "ascending";
arrayAppend(variables.sortKeys, variables.sortKey);
variables.sortKey = structNew();
variables.sortKey.keyName = "name";
variables.sortKey.sortOrder = "ascending";
arrayAppend(variables.sortKeys, variables.sortKey);
// do the sorting
variables.persons_sorted = sortArrayOfObjects(
arrayToSort = variables.persons,
sortKeys = variables.sortKeys,
doDuplicate = false,
useGetterMethods = false);
</cfscript>
<h3>Unsorted:</h3>
<cfdump var="#variables.persons#">
<h3>Sorted:</h3>
<cfdump var="#variables.persons_sorted#">
Hey Martijn! This looks to be a terrific resource for CFML developers. I’m going to play around with it and let you know how it goes. Thanks again for plugging this functionality in!