On my application.cfc file, I would like to have set a variable:
application.gsversion = "Version 0.1.#year(x)#.#month(x)#.#day(x)#";
where x has the application.cfc's current modified date.
Add something like this to your onApplicationStart() method in Application.cfc:
var objAppFile = fileopen(expandpath('./Application.cfc'), 'read');
application.gsversion = "Version 0.1.#year(objAppFile.lastmodified)#.#month(objAppFile.lastmodified)#.#day(objAppFile.lastmodified)#";
fileclose(objAppFile);
Related
I'm using Lucee CFML to create a website.
I have a global variable stored in application.cfc like this:
component {
application.globalquery;
}
On the second page of the website, I assign a value to that variable:
<cfscript>
myquery = ["object1", "object2", "object3", "object4", "object5"];
application.globalquery = myquery;
</cfscript>
On a third page, I dump the globalquery variable:
<cfscript>
dump(var="#application.globalquery#");
</cfscript>
But the result of this dump is string: empty
The expected behavior should be, that it contains the 5 objects of myquery.
Why isn't that the case?
You're resetting the value on every request.
By putting the definition at the root of the component:
component {
application.globalquery;
}
You're essentially telling CF to run that code on every request, like this:
component {
function onRequestStart() {
application.globalquery;
}
}
You need to define that variable only once, when the application starts, like this:
component {
function onApplicationStart() {
application.globalquery;
}
}
From then on, the value should only change when you tell it to change.
Here's more info on Application.cfc. There may be a few differences between Adobe CF and Lucee.
I've inherited a project where there are a number of remote CFC's opened up for some Ajax requests and inside most methods in the CFC have the following:
<cfset var this.response = true />
Now I've never seen the var and this scope used together like this so I'm really not sure what to make of it so I guess my questions is:
Are there any issues with how this was coded? If so, are they major enough that I should put in
the effort to update all the CFC's to something like <cfset var
req.response = true />?
Here is a quick example of what I'm seeing:
<cfcomponent>
<cffunction name="check_foo" access="remote" returnformat="plain">
<cfargument
name = "isfoo"
type = "string"
required = "false"
default = "nope"
hint = "I check the string for foo"
/>
<cfscript>
/*setup new response*/
var this.response = false;
/*check for foo*/
if( !findnocase( "foo", arguments.isfoo ) ) {
/*no foo!*/
this.response = false;
}
return this.response;
</cfscript>
</cffunction>
</cfcomponent>
.
Updates:
Based on the feedback/answers below I've replace all instances of var this. Thanks again to everyone that helped out!
.
update: upon checking your dump, the "this" in var this is still this this scope, not local.this.
It is setting the response to the this scope, and it works in this case because because the CFC is instantiated every time it's being invoked remotely. However, it'd be best to rename this into something else to ensure thread-safety in case the method is invoked by other CFC as public method.
Using var this is the same as using this.
Dumping the local scope will include local variables as well as the Arguments and This scopes. (Can't find this documented; but I get this result in a bare cfc, and you got it in your screenshots.)
Because your function is access="remote" you'll be getting a new instance of the cfc on every call, and therefore a bare This scope. So those are "safe", but still a bad idea.
If there is any use of var this in non-remote functions then you will be getting undesired persistence and may suffer race conditions that result is invalid data.
Relevant CF documentation:
"Methods that are executed remotely through Flash Remoting and web services always create a new instance of the CFC before executing the method."
"Variable values in the This scope last as long as the CFC instance exists and, therefore, can persist between calls to methods of a CFC instance."
I am using ColdFusion 8.0.1.
I am writing a little code in the application file that will look at the URL. If any of a certain type of property is passed, I don't want to update a property in a SESSION structure.
Basically, if a visitor accesses any page that has to do with our registration process, we do not want to update the SESSION.UserInfo.ReturnToURL variable. For every other page they access, we want to update the variable.
All pages that have to do with the registration process will have "myiq.reg" in the URL. If this were the case, I would use the code below.
// DETERMINE WHETHER TO UPDATE RETURNTOURL
if (not structKeyExists(URL, "myiq.reg")) {
URLString = "http://" & CGI.SERVER_NAME & CGI.SCRIPT_NAME & CGI.QUERY_STRING;
SESSION.UserInfo.ReturnToURL = URLString;
}
But it's not that simple. My people want to be able to pass other properties that are similar, like this:
myiq.reg_confirm
myiq.reg_password
myiq.reg_save
I need to be able to soft code these to work with any registration page that they might create in the future. Basically, I need something like this :
if (not structKeyExists(URL, "myiq.reg*")) {
SESSION.UserInfo.ReturnToURL = URLString;
}
Notice the WILDCARD after "myiq.reg". I've tried this, but it doesn't work.
How do I code this so that any page that is access with a URL property that begins with "myiq.reg" is ignored?
You could get a structKeyList() of the URL scope, and just do a regex find in that. Something like:
reFindNoCase("(?:^|,)myiq\.reg", structKeyList(URL))
(only superficially tested)
You could improve the regex a bit if you wanted to more accurately match actual variable name patterns rather than just any occurrence of myiq.reg in the string.
Something like this perhaps...
res = '';
params = StructKeyList(url);
for(i=1; i lte ListLen(params); i++) {
param = listGetAt(params, i);
if (CompareNoCase(Left(param, 8), 'myiq.reg') eq 0) {
res = param;
break;
}
}
I am looking for a quick and dirty way to query the layouts files of a particular page by its friendly url. This is probably easy, but I can't find the solution.
Basically I want to say something like the following. Pseudo-code:
var mainpage = Sitecore.EasyQueryUtility.GetItemByFriendlyUrl(requestedUrl);
or
var mainpage = Sitecore.EasyQueryUtility.GetOppositeOfFriendlyUrl(friendlyurl);
It sounds like you want to do two things here:
Determine an item based on its rendered URL in the address bar (i.e. friendly URL)
Determine the layout being used by the item once you determine the item.
If those are correct, hopefully this can help you out:
Note: untested code I did on-the-fly
// if you have the full URL with protocol and host
public static Item GetItemFromUrl(string url)
{
string path = new Uri(url).PathAndQuery;
return GetItemFromPath(path);
}
// if you have just the path after the hostname
public static Item GetItemFromPath(string path)
{
// remove query string
if(path.Contains("?"))
path = path.split('?')[0];
path = path.Replace(".aspx", "");
return Sitecore.Context.Database.GetItem(path);
}
Once you have the item you can get the layout's name like so:
item.Visualization.GetLayout(Sitecore.Context.Device).Name;
Or the layout's physical file path to the ASPX:
item.Visualization.GetLayout(Sitecore.Context.Device).FilePath;
If you want to get the path of the aspx file which is used for the layout of your page, you can use:
Sitecore.Context.Item.Visualization.Layout.FilePath
I may have misunderstood you but if you want to control the format of friendly URLs you can set several attributes via the Sitecore.Links.UrlOptions class and pass an instance of this in to the link manager. See here for more details. (Note - the LinkManager class is only available from SiteCore 6 I beleive).
The code you would end up with looks like this:
Sitecore.Links.UrlOptions urlOptions = (Sitecore.Links.UrlOptions)Sitecore.Links.UrlOptions.DefaultOptions.Clone();
urlOptions.SiteResolving = Sitecore.Configuration.Settings.Rendering.SiteResolving;
string url = Sitecore.Links.LinkManager.GetItemUrl(item, urlOptions);
You can then set fields like AddAspxExtension on the urlOptions you pass in.
As you can see, the process is reliant on you passing in an item - whether it be obtained via the current context or retrieved from the URL you start off with.
If you were asking about obtaining the layout definition item, take a look at this which shows you how.
I'm using CF 7 and this code is not returning any files:
<cfset fileLocation = "\\server\uploader\pass-fail">
<cfdirectory
action = "list"
directory = fileLocation
name = "pass_fail_files"
>
<cfdump var="#pass_fail_files#" expand="yes" label="files in pass-fail" >
<cfoutput>#pass_fail_files.name#</cfoutput>
<cfoutput>#pass_fail_files.directory#</cfoutput>
<cfoutput>#pass_fail_files.size#</cfoutput>
<cfoutput>#pass_fail_files.type#</cfoutput>
<cfoutput>#pass_fail_files.dateLastModified#</cfoutput>
<cfoutput>#pass_fail_files.attributes#</cfoutput>
<cfoutput>#pass_fail_files.mode# </cfoutput>
I have checked to make sure that the directory indeed has several text files. But when I run the code, all I get is:
alt text http://img682.imageshack.us/img682/5603/nofiles.png
What am I doing wrong?
I've just tried this:
<cfset fileLocation = "\\192.168.8.20\websites">
<cfdirectory
action = "list"
directory = "#fileLocation#"
name = "pass_fail_files"
>
<cfdump var="#pass_fail_files#" expand="yes" label="files in pass-fail" >
On CF7, CF8 and Railo, and works everytime.
Notice I updated your code so it uses the directory attribute as directory = "#fileLocation#" as opposed to directory = fileLocation.
Trying your code, I never got results, but didn't get errors either. Changing it to use double-quotes and hashes did the trick, as it stopped using it as a variable.
Hope it helps you.
My first question would be, does the ColdFusion Service User have read access on folder?
Actually, I think your code should be
<cfdirectory
action = "list"
directory = "#fileLocation#"
name = "pass_fail_files"
>
I think right now, you're telling it to look in a directory named "fileLocation".
Assuming you've done all the latest CF7 updates/patches/hotfixes..