My solution to the Friday Puzzle

This post is more than 2 years old.

Based on my post from yesterday, here is my 5 minute 'quick stat' solution to the puzzle. Note, this is not thread safe and it will quickly destroy my server (most likely), but it works!

I added this to Application.cfm, at the bottom, before my last cfsetting.

<cffunction name="getCurrentURL" output="No" access="public" returnType="string"> <cfset var theURL = getPageContext().getRequest().GetRequestUrl().toString()> <cfif len( CGI.query_string )><cfset theURL = theURL & "?" & CGI.query_string></cfif> <cfreturn theURL> </cffunction> <cfset s = structGet("application.data")> <cfset p = getCurrentURL()> <cfif not structKeyExists(s, p)> <cfset s[p] = 0> </cfif> <cfset s[p]++>

The UDF comes from CFLib of course. It handles both query string and path_info CGI variables so it works well on the blog.

To display it, I wrote this script:

<cfset sorted = structSort(application.data,"numeric","desc")> <table width="100%" border="1" cellpadding="5"> <tr> <th>Page</th> <th>Count</th> </tr> <cfloop index="a" array="#sorted#"> <cfoutput> <tr> <td>#a#</td> <td>#numberFormat(application.data[a])#</td> </tr> </cfoutput> </cfloop> </table>

Nothing too complex here outside of the cool structSort function which works perfectly for this example. If you are bored, you can see this in action here.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Phillip Senn posted on 12/7/2008 at 1:39 AM

What does this stmt do?
<cfset s = structGet("application.data")>

According to the CFML reference, it returns
"An alias to the variable in the pathDesired parameter."
Which I think it means it simply creates a pointer, or a shortcut (ie: not a clone or copy of) the variable called "data" that is in the application scope.

The book then says:
If necessary, StructGet creates structures or arrays to make pathDesired a valid variable "path."
I'm not sure what the implications are for that.
But it almost sounds like it would create a clone, or a copy "if necessary".

What is the definition of a valid variable "path"?

Comment 2 by Phillip Senn posted on 12/7/2008 at 1:52 AM

Where did you learn about:
getPageContext().getRequest().GetRequestUrl().toString()?

Is this the equivalent to something more familiar?

Comment 3 by Phillip Senn posted on 12/7/2008 at 2:01 AM

<cfif not structKeyExists(s, p)>
<cfset s[p] = 0>
</cfif>
<cfset s[p]++>

Q: Can you use what looks like array notation on structures?

If the value of p="Index.cfm", then is this in effect saying:

<cfif not structKeyExists(s, "Index.cfm")>
<cfset s("Index.cfm") = 0>
</cfif>
<cfset s("Index.cfm")++>
?

Comment 4 by Raymond Camden posted on 12/7/2008 at 2:29 AM

Wow, a lot of questions.

1) structGet. structGet basically says, "If X doesn't exist, make it. Then return a pointer." So imagine X="application.foo.moo". CF will say "Does the Application struct exists?" If no, make it. Then it wil say, does Foo exist as a struct in Application? If not, make it.

And so on and so on.

It is basically a quick way to make a deeply nested struct. You can also do Application.foo[5], and it will create foo as an array.

2) getPageContext() - It's documented. :) That's in the CF ref, and then you get access to a Java object which is also documented. I didn't find this myself, it was in the UDF.

3) Your last question confuses me. You use bracket notation with structs, just like arrays, but arrays are only indexed by #s, structs are indexed by string based keys.