Archive for the ‘Structs’ Category

Converting a complex list to a struct

Wednesday, February 10th, 2010

I created an image upload for some projects.  Having dealt with image uploads in the past I decided that I would just do some after hours work in order build one that I could give to the designers and let them go to town with it without hopefully needing my help.  I did this like many plugins with some settings.  So for each upload the designer has a list of settings where they can specify MIME types, destinations, sources, names, database table names, and so forth.  One setting that is available is the ability to specify a set of sizes to resize the original image to.

While I naturally wanted to pass these values in as an array of values that my method could use to do the actual resizing I knew that each time the upload was implemented I would have to stop what I was doing to create the array of images and their resizing data.  Not interested.

My solution was what I’m calling here a complex list.  By complex I simply mean that it has two sets of delimiters in it.  In my case commas and semi-colons.  I chose this route over the array because it’s something more along the designers line of work.  No fancy methods and square brackets.  Just some good ole’ quotes, commas, and semi-colons.  So let’s look at an example of a complex list, and then we’ll take a look at a method that will convert that list into a struct that the image upload method can work with.

The Calling Page

<!--- SET A STRING THAT CONTAINS IMAGE DATA IN THE FORM
OF WIDTH, HEIGHT, TYPE; WIDTH, HEIGHT, TYPE; AND SO ON.
SEMI-COLONS SEPARATE IMAGES AND COMMAS SEPARATE IMAGE
SPECIFIC DATA. --->
<cfset VARIABLES.images = "200,200,large;150,150,medium;100,100,small">

<!--- RUN METHOD TO CONVERT DATA LIST TO STRUCT --->
<cfinvoke 	component="path.to.cfc.complex_lists"
			method="convertComplexList"
			returnVariable="complex_lists" >

	<!--- PASS IN LIST ABOVE --->
	<cfinvokeargument name="imagesizes" value="#VARIABLES.images#" />

</cfinvoke>

<!--- DUMP THE STRUCT --->
<cfdump var="#complex_lists#">

(more…)

Accessing a query resultset by row number

Tuesday, January 12th, 2010

I ran into a little issue this morning of needing to access a query resultset not by column or item id or anything usual.  Instead I needed to access data in the query via the row number.  This is not something that occurs often for me.  In fact this is the first time I’ve encountered this.

I checked Adobe’s docs and found no method immediately accessible for getting a row of my choice.  The closest I found was the currentRow() method that can be used when looping through a query.

Knowing Java has a slew of methods for working with query result sets I turned to the java docs.  Sure enough I found a way to use java methods to return specific data about a row of my choice.  Afterwards, I found on Ben Nadel’s blog a post about converting a query into an array.  He posts there a way of accessing the query object as a struct.  So let’s take a look at a quick example of how to use both.

First let’s create a query to work with.

Create Query

<!--- CREATE LIST --->
<cfset VARIABLES.listofcolors = "blue, red, purple, green, yellow, magenta">

<!--- CREATE A COUNTER --->
<cfset VARIABLES.counter = 22>

<!--- CREATE QUERY --->
<cfset VARIABLES.getQuery = querynew("id, colors")>

<!--- LOOP OVER COLORS --->
<cfloop list="#VARIABLES.listofcolors#" index="VARIABLES.i">
	<!--- CREATE A NEW ROW IN QUERY --->
	<cfset queryaddrow(VARIABLES.getQuery, 1)>

	<!--- ADD DATA --->
	<cfset querysetcell(VARIABLES.getQuery, "id", VARIABLES.counter)>
	<cfset querysetcell(VARIABLES.getQuery, "colors", VARIABLES.i)>

	<!--- INCREASE COUNTER BY 1 --->
	<cfset VARIABLES.counter = VARIABLES.counter + 1>
</cfloop>

(more…)

Getting struct data with variables in Coldfusion

Saturday, January 2nd, 2010

I thought I’d write a quick post about something that I thought might trip people up every now and then.  And that is getting data from a struct by passing in a variable that represents some portion of the struct holding the data.  I’ll just give a few quick lines of code to represent what I’m talking about.

<!--- CREATE A STRUCT --->
<cfset VARIABLES.myStruct = structnew()>

<!--- SET A MESSAGE INTO OUR STRUCT --->
<cfset VARIABLES.myStruct.message = "This is my message.">

<!--- SET A VAR TO REPRESENT THE MESSAGE PORTION OF OUR STRUCT --->
<cfset VARIABLES.the_message = "message">

<!--- GET MESSAGE USING THE VARIABLE --->
<cfdump var="#VARIABLES.myStruct[VARIABLES.the_message]#">

All we’re doing here is creating a struct with a message stored in it. I think it’s pretty common for Coldfusion developers to use dot syntax to retrieve data from structs. But this creates a little bit of a problem when the portion of the struct that we need to get data back from is represented by a variable that we have set. I find this happening most often when I use loops to get or set data into a struct.

Nonetheless, in the above I’m retrieving my message from the struct.  Yes the easiest way to get the message is with dot syntax.  To use it this way we would write <cfdump var=”#VARIABLES.myStruct.message#”>.  But let’s just say that for whatever reason we’re not at liberty to write message directly.  Instead we need to represent ‘message’ with a variable set for whatever reason be it looping, reusability, or just generally passing data.  So I’ve set a variable to hold a string equal to ‘message’.  To get the message from the struct using this variable we need to write it as <cfdump var=”#VARIABLES.myStruct[VARIABLES.the_message]#”>

So to get data from a struct using a var just mix your dot syntax with some square brackets and voila you get the message.

Dynamically displaying struct data with a loop

Wednesday, December 2nd, 2009

This post is a follow-up to a previous post. If you don’t think you need to read it or just don’t feel like it, I’ll just dump the code and a snapshot of how our struct that we’ll be looking at is structured.  However, if you are interested, you can check it out at Creating a Struct by Looping. Anyway, here’s the code and snapshot from the other post.

<!— SET THE NUMBER OF LOOPS TO RUN —>
<cfset VARIABLES.loops = 5>

<!— CREATE A STRUCT —>
<cfset VARIABLES.data = structnew()>

<!— SET A DATA INTO THE STRUCT.  THIS REPRESENTS HOW TO HARDCODE DATA INTO THE STRUCT —>
<cfset VARIABLES.data.working = true>

<!— RUN OUR LOOP —>
<cfloop from=”1″ to=”#VARIABLES.loops#” index=”VARIABLES.i”>

<!— SET DATA DYNAMICALLY INTO THE STRUCT —>
<cfset “VARIABLES.data.loops.loop#VARIABLES.i#” = “loop_data_” & VARIABLES.i>

</cfloop>

<!— DUMP OUR STRUCT —>
<cfdump var=”#VARIABLES.data#”><br /><br /><br />

What our struct looks like.

What our struct looks like.

So what we’re going to do is loop over the ‘loops’ portion of our struct and output each of the 5 loop labels data.  So we are wanting to show the data from our struct like:

OUTPUT OUR LOOPED DATA IN OUR STRUCT

DATA 1: loop_data_1
DATA 2: loop_data_2
DATA 3: loop_data_3
DATA 4: loop_data_4
DATA 5: loop_data_5

The key is that we want to loop over the struct holding this data and output it dynamically.  That way if it is 5 loops or 200 loops the data will always output the same and account the for the varying amounts of data.  Let’s look at the code first.

OUTPUT OUR LOOPED DATA IN OUR STRUCT<br /><br />

<!— GET THE LENGTH OF OUR LOOPS STRUCT —>
<cfset VARIABLES.structLength = structcount(VARIABLES.data.loops)>

<!— LOOP THROUGH OUR STRUCT AND OUTPUT THE VALUES —>
<cfloop from=”1″ to=”#VARIABLES.structLength#” index=”VARIABLES.i”>

<!— SET THE NAME OF THE LABEL OF EACH OF SET OF DATA IN THE LOOP —>
<cfset VARIABLES.loopdata = “loop” & VARIABLES.i>

<!— GET THE DATA WE SET FOR THAT LOOP —>
<cfoutput>
<strong>DATA #VARIABLES.i#</strong>: #VARIABLES.data.loops[VARIABLES.loopdata]#<br />
</cfoutput>

</cfloop>

First we need to get how many sets of data is in our struct.  Remember that the struct that I’m referring to here is the struct inside of the larger struct.  You can get the amount of data in a struct by using the handy ’structcount()’ method.  Just pass in the struct you want to get the count of. Afterwards, we can loop from 1 to however many sets of data is stored in our struct.  Simple enough so far.

Once inside the loop we need to grab the first set of data in the struct we are looping over.  This is the data with a label of ‘loop1′.  First we set a var that will update with each loop to create the new label.  So loop 1 will be set to ‘loop1′, second loop ‘loop2′, and so on.  Once we have this set we can get our data by using brackets as opposed to just continuing the dot notation.  For example we could get the value of ‘loop1′ by hardcoding the following: VARIABLES.data.loops.loop1.  But that is just going to output the first set of data 5 times.  In order to pass a dynamic value into our struct path that points to our value, we need to use the brackets.  Using brackets, we can pass in our var that sets its value dynamically with each loop, which will output each of the 5 sets of data in our struct.

Creating a struct by looping

Wednesday, December 2nd, 2009

On a regular basis I find myself needing to create a Coldfusion struct dynamically with a loop.  Although creating a struct in Coldfusion couldn’t be simpler or more intuitive (in my opinion), creating a struct dynamically is a little more problematic.  The problem is that you can’t set the name of your labels in your struct that holds your looped data dynamically.

So for example, let’s say that we want to create a struct that holds five sets of data labeled loop1 that is equal to loop_data_1, loop2 that is equal to loop_data_2, and so on up to loop 5.  When we dump our struct we want it to look like the following.

Dynamically created data in a struct

Dynamically created data in a struct

So let’s look at the code that we need to write to accomplish this.

<!— SET THE NUMBER OF LOOPS TO RUN —>
<cfset VARIABLES.loops = 5>

<!— CREATE A STRUCT —>
<cfset VARIABLES.data = structnew()>

<!— SET A VALUE INTO THE STRUCT.  THIS REPRESENTS HOW TO HARDCODE DATA INTO THE STRUCT —>
<cfset VARIABLES.data.working = true>

<!— RUN OUR LOOP —>
<cfloop from=”1″ to=”#VARIABLES.loops#” index=”VARIABLES.i”>

<!— SET DATA DYNAMICALLY INTO THE STRUCT —>
<cfset “VARIABLES.data.loops.loop#VARIABLES.i#” = “loop_data_” & VARIABLES.i>

</cfloop>

<!— DUMP OUR STRUCT —>
<cfdump var=”#VARIABLES.data#”>

Everything here is fairly straightforward up until we get to setting the data into the struct inside our loop.  What we need to do is set the label of our data to be “loop” and then whatever the current loop index is.  So if we are on our third loop our label will be “loop3″.  The problem is that you can just set a label by writing VARIABLES.data.loops.loop#VARIABLES.i#.  You’ll get yourself a nice little cf error something along the lines of:

Error thrown when creating a dynamically named struct label.

Error thrown when creating a dynamically named struct label.

To get around this all you need to do is wrap your label in quotation marks as is above in the code.  So VARIABLES.data.loops.loop#VARIABLES.i# becomes “VARIABLES.data.loops.loop#VARIABLES.i#”.  And that is it.  Your now able to create and label your struct dynamically.  To see how to output this data dynamically I’ve written another post on Dynamically Displaying Struct Data with a Loop.  Feel free to check it out as well.

Looping through a Coldfusion struct

Monday, November 9th, 2009

I recently encountered a little problem that I didn’t off-hand know how to fix. My problem was that I have a cfc that sets certain errors into a struct and returns the struct to the calling page. The idea of course is that these errors will never be used. Ha! However, in the real world I needed to loop through my struct and output any error messages to the user that may have occurred. I didn’t know at the time how to do this. I tried several different things, including treating the struct like an array. Nothing seemed to work. I searched the blogs and docs and I’m sure that I ran into something that is doing the same thing I’m demonstrating here, but I must have failed to see it. As such I wanted to display just how, surprise – surprise, simple this turned out to be.

Create the Struct

<!— create a struct to hold several errors —>
<cfset VARIABLES.errors = structnew()>

(more…)