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.
Archived Comments
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"?
Where did you learn about:
getPageContext().getRequest().GetRequestUrl().toString()?
Is this the equivalent to something more familiar?
<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")++>
?
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.