Orange is my favorite color

The title is a little ambiguous but I don’t know how else to describe the behavior that Java gives you where the following request:

/test.cfm?id=foo&id=bar&id=snafu

or form with set of checkboxes:

<input type="checkbox" name="id" value="1000" /> 1000<br />
<input type="checkbox" name="id" value="1001" /> 1001<br />
<input type="checkbox" name="id" value="1002" /> 1002<br />

can be transformed using request.getParameterValues() into arrays because we pass multiple values for the same variable in the request. PHP also has auto-conversion into arrays. ColdFusion has no such thingy see update below*.

In working with my Javascript contractor this morning on some AJAX routines, I took a few minutes to try and emulate the behavior to support receiving data from Ext JS components. I came up with the following UDF which works with both GET and POST:

<cffunction name="getVarAsArray">
	<cfargument name="field" type="string" required="true" />

	<cfset var arr = arrayNew(1) />
	<cfset var data = "" />

	<cfif CGI.request_method EQ "GET">
		<cfset data = CGI.query_string />
	<cfelse>
		<cfset data = toString(getHTTPRequestData().content) />
	</cfif>

	<cfloop list="#data#" delimiters="&" index="item">
		<cfif listFirst(item, "=") EQ arguments.field>
			<cfset arrayAppend(arr, listLast(item, "=")) />
		</cfif>
	</cfloop>

	<cfreturn arr />
</cffunction>

If you were to run the first request described above and run getVarAsArray(“id”), you would get the following array back:

array
1 foo
2 bar
3 snafu

I don’t think getVarAsArray is a very catchy name nor incredibly descriptive of what it does. Can someone suggest a better name?


Barney is a Smarty Pants *UPDATE*

I knew, since ColdFusion MX is based on Java, that there must be a way to get at the Java getParameterValues() but I didn’t have the patience to track it down and I’m not a big user of getPageContext(). As Barney explains in his comment below, you can get at it with this simple line of code eliminating the need for the above UDF:

array = getPageContext().getRequest().getParameterValues('id')

The one difference is that this approach will throw an error if the variable ID doesn’t exist whereas my UDF will return an empty array. It’s easy enough to fix by wrapping with a structKeyExists() to check for the variable first. In most cases you’ll be expecting a specific variable so it shouldn’t be a problem.

Thanks to Barney for teaching me something new – cheers! :)

6 Comments

  1. Stephen Judd said:

    on December 2, 2008 at 2:45 am

    In my experience, url.id or form.id will end up being a list of the values sent with the request. Why not just use ListToArray(url.id) or ListToArray(form.id)? Or am I missing something obvious?

  2. brian said:

    on December 2, 2008 at 9:20 am

    @Stephen – that will work if every variable has a non-empty value AND there are no commas in the values. ColdFusion will remove blank values when processing lists and I believe (although I haven’t tested) that if one of your values has a comma in it, you would wind up with more array entries than actual variables.

    That isn’t a problem if you’re passing discrete integers for example but is an issue if you’re passing free-form text entry which could legitimately contain commas.

    I should have pointed this out in my posting – thanks for the comment!

  3. Barney said:

    on December 3, 2008 at 9:24 am

    How about just using getPageContext().getRequest().getParameterValues(“id”). Save you a bunch of manual string parsing.

  4. brian said:

    on December 3, 2008 at 11:32 am

    @Barney: I knew there must be a way to get to the request object but I didn’t have the patience to track it down and I’m not very familiar with the page context object. You are the man, that is the best way possible!

  5. Brian Kotek said:

    on December 11, 2008 at 5:08 pm

    I wrote a CFC a while back that converts any arbitrarily nested form fields that use structure or array syntax into actual structures and arrays on the CF side. It goes a lot deeper than just turning the fields into a 1D array, you might have a look at it: http://formutils.riaforge.org/

  6. brian said:

    on December 12, 2008 at 8:50 am

    @Brian – cheers for that, formutils is more than I wanted to accomplish in this short exercise but it could be quite valuable otherwise. This might have saved my javascript guy from having to encode arrays and objects as JSON to send over to the server.

    I’m starting to feel like there is enough open source or shared coldfusion projects and software out there that it’s hard to conclusively search for something before reinventing the wheel. Rinaldi’s list, RIAForge and others are helping but the growth of the CF community also creates X many more places to look before you leap.

{ RSS feed for comments on this post}