A reader asks:
I have a CF app that needs the codebase to be able to run on both CF6.1 and CF7.The function queryNew() can take 2 params in CF7, but not CF6.1.
How can I code round this?
I have tried this, but it doesn't work:
qMyQuery = false;
iCFMajorRelease = listFirst(server.ColdFusion.ProductVersion,",");if(iCFMajorRelease LT 7){
qMyQuery = queryNew("oneColumn,twoColumn");
} else {
qMyQuery = queryNew("oneColumn,twoColumn","CF_SQL_VARCHAR, CF_SQL_VARCHAR");
}
So as he probably discovered - this code will throw an error when run on ColdFusion 6, even though, in theory, the code doesn't run. The problem is that the CFML is getting compiled (or interpreted, I always forget the right term) and CF6 simply won't like the syntax used in the second cfif branch. I haven't seen this before with functions, but have seen it in the past when trying to use a tag that didn't exist in a previous version. You can see this for yourself in CFMX7 by doing the following:
<cfif 0>
<cfset foo = queryNew("o","cf_sql_varchar", "9")>
</cfif>
So how do you get around this? By cfincluding. If you move the code that will only run in CFMX7 to a cfinclude, than CFMX6 will not have a problem. (As long as you don't accidently screw up your cfif conditional.) For an example of this - see how I do charting in Galleon. In order to support BlueDragon, I moved the charting to it's own include file.
Archived Comments
Great tip!
Jus checking out your Lighthouse app, great stuff there too!
MD
Hi Ray,
that was quick! I asked the question...
It's from with-in a CFC and I still feel uneasy about cfincluding in a CFC.
What I did in the end was a *gulp* evaluate.
so the code ended up like this...
qMyQuery = false;
iCFMajorRelease = listFirst(server.ColdFusion.ProductVersion,",");
if(iCFMajorRelease LT 7){
qMyQuery = queryNew("oneColumn,twoColumn");
} else {
sCF7 = 'queryNew("oneColumn,twoColumn","CF_SQL_VARCHAR, CF_SQL_VARCHAR")';
qMyQuery = evaluate(sCF7);
}
Thanks for your response!
One way to address this problem is to create some custom UDF libraries that replace the existing CF functionality. You can then load the correct library depending on the version of CF you're using.
So, instead of using the built-in queryNew(), you'd write a UDF called createQuery() (or whatever name you prefer--you could use queryNewUDF() or some nomeniclature that indicates it's a custom version of an existing function.)
You could also encapsulate this idea into a CFC.
Dan, that is a darn good idea. In my case, the last time I did it it wasn't functionality per se - I was hiding a whole section form BD, but for the reader's post, your idea is dead on perfect.
Thanks for the suggestion Dan.
We just needed to hear that about the time CF7 was released!
Hind site is 20-20!
I'm a little confused...how would the queryNewUDF() indicate that it is a custom function of an existing function?
The UDF would handle the branching logic - ie, if cf6, do this, else do that. It is basically a wrapper.
I had issues like this when I was doing the conversion of Lighthouse. The biggest issue for me is the tag differences. If there is even one attribute different it will throw an error and you can't try or catch the error because CF doesn't handle it. Would having logic for a UDF or a CFC that says
if CF 6
createobject(cf6)
else
createobject(cf7)
Or would that compile them both?
At the risk of sounding too proud of stating the obvious, why not just use the code that works in 6 (and presumably in 7)?
qMyQuery = queryNew("oneColumn,twoColumn");
In our shop, we have mx6.1 in system test and production, and 2/3 of our developers use the same. I have been on various iterations of mx7 for about a year or so now, and the only gotcha that has hit me was in using tag help based on mx7 (I believe it was an extra attribute to the cffile tag which mx6 choked on). Until we move to 7 in production, I have to continue to code to mx6 and watch myself on a few new features in 7, but I have yet to run into a problem (at least with most basic tags) where something that works in 6 did not work in 7.
In the simple case you described, my method is probably overkill, but it does work well for bigger cases, like where I wnted to support BlueDragon in my code and had to hide the charts.