I have the line:
<cfif isArray( this.filters[this.name] )
AND this.filters[this.name].Contains(JavaCast("string",par.fval)) >
which is generating an 'Invalid CFML Construct: contains' error message.
Am I missing something or are the java methods not available when an array is created?
For me the error is a little more explicit:
Invalid CFML construct found on line 1 at column 71.
ColdFusion was looking at the following text:
Contains
And it's saying that because contains is a reserved-ish word in CFML, and something about the combo of that and the square brackets is fooling the parser into thinking there's a problem.
However this sort of thing should work:
<cfset proxy = this.filters[this.name]>
<cfif isArray( this.filters[this.name] ) AND proxy.Contains(JavaCast("string",par.fval)) >
</cfif>
NB: this is a vagary of ColdFusion... Railo does not have this problem. I'm gonna blog it & cross-reference here.
Related
We have list of reserved keyword that we don't want our clients to be able to use in out system. So we perform a search using REFind.
Here is the code:
<cfset reservedKeywords = "stop,end,quit,cancel,help,test">
<cfset foundArray = REFind("(?i)(" & ListChangeDelims(reservedKeywords, "|") & ")"
, form.keyword, 1, true)>
<cfif foundArray.pos[1] gt 0>
<cfoutput>
<script language="JavaScript">
alert('Keyword "#mid(form.keyword, foundArray.pos[1], foundArray.len[1])#" has been reserved.');
history.go(-1);
</script>
</cfoutput>
<cfabort>
</cfif>
So everything works great.... but we do run into a problem when a keyword is searched that has one of the reserved word IN the keyword. So if "Blended" is submitted, it will be flagged as having the reserved word "end".
Is there a way to perform an absolute search where it takes into account the whole keyword?
I've been trying to edit and play around with the code but just can't get it to work.
Any suggestions would be greatly appreciated.
Thank you!
Use listFindNoCase() instead of REFind().
The way you are currently checking is if one of the elements in the list matches form.keyword - which is why 'blended' gets tagged as 'reserved' when it shouldn't - however, you should be checking if form.keyword matches any items in the list - a subtle, but important, distinction.
reservedWords = "stop,end,quit,cancel,help,test";
reservedWordUsed = listFindNoCase( reservedWords, form.keyword );
if( reserveWordUsed ){
// do the JS stuff here
}
I am trying to invoke a component using the new keyword but it is not working.
The following method below works fine:
<cfset test = CreateObject("component", "test-objects.shipping_new").init(bar="Blah", foo="boom")>
But when I try to use the following:
<cfset test = New test-objects.shipping_new(bar="Blah", foo="boom") />
I get the error tag cfset is not closed. The code above is the first line in the file I am trying to invoke it from, unless I am missing something the tag looks closed to me. I am using Lucee 4.5 if that makes a difference.
The problem is the hyphen:
If the folder name or CFC name has hyphen, use the following syntax:
cfObject=new "cfc-path"(constructorParam1,...)
I saw this code example in a recording and wanted to know what the colon syntax did. I searched the docs, but I wasn't able to find any info on it:
weather.subscribe(observer: application.observers.currentConditions);
I know we can use colon in CF9 for ternary operators:
result = (condition) ? true : false;
But in this case it looks like it's being used to provide named arguments; so what's it doing there?
<cfset result = obj.func(arg:value,thing:42) /> I looked at this and
went blink, blink... That can't be right! You can't use colons for
named arguments! Er, can you? Well, apparently you can.
http://corfield.org/blog/post.cfm/Learn_something_new_every_day_named_arguments
Yes, you are allowed to use both. I think it's a matter of preference. You can even mix.
Try this and see, mocked up some test function:
<cffunction name="testFunction" returntype="void" hint="I just spit out the arguments I get">
<cfdump var="#arguments#" label="arguments">
</cffunction>
<cfset testFunction(arg1:"hello",arg2:"world") />
<cfset testFunction(arg1="hello",arg2="world") />
<cfset testFunction(arg1:"I can mix",arg2="my named argument syntax") />
Personally, I prefer = for named arguments. You might also notice that if you use IntelliJ IDEA for your ColdFusion development that they do not recognize the colon syntax, so for better parsing you would want to use the = syntax. I can't speak for other IDEs
Looks like a typo to me. In ColdFusion you would use an equals sign (=) not a colon to used named arguments.
Your example would become:
weather.subscribe(observer = application.observers.currentConditions);
Let's say i've just parsed someone else's XML document which is a response to an API request. I want to know if a value nested deep inside exists. If my API request worked, it will be in the same place every time. If my API request fails, the root of the XML is very different.
If I try <cfif structKeyExists(myStruct.level1.level2.level3, 'myTarget')> on a failed api request, I get the fatal error: Element LEVEL1.LEVEL2 is undefined in MYSTRUCT.
Of course, I could try to depend on the root level of the XML telling me of success or failure, and not looking for the result if it failed, but... barring that solution, what should i do?
Do i need to check for the existence of each level of the struct? As in:
<cfif structKeyExists(myStruct, 'level1')
and structKeyExists(myStruct.level1, 'level2')
and structKeyExists(myStruct.level1.level2, 'level3')
and structKeyExists(myStruct.level1.level2.level3, 'myTarget')>
<!--- ... --->
</cfif>
This is not a real-world problem, this is just something i've faced too many times. Please don't tell me solutions that involve changing the API or solutions like those in the third paragraph.
Thanks!
edit: i should have mentioned why i can't use isDefined() - some of the keys do not have syntactically valid names, so isDefined() throws an error, eg myStruct.level1[42].level3
XMLSearch
I would use the parsed XML document (i.e. xmlDoc) and XMLSearch:
<cfset xmlDoc = xmlParse(responseData)>
<cfset nodes = XmlSearch(xmlDoc, '/level1/level2/level3/myTarget')>
<cfif arrayLen(nodes)>
<!--- do something, you have the "nodes" array to work with too --->
</cfif>
xpath for XMLSearch() assumes the structure keys are nodes. You would need to modify accordingly if, for instance, 'myTarget' is an attribute of a node.
StructFindKey
Another way of doing this would be StructFindKey.
<cfset result = structFindKey(myStruct, "myTarget")>
<cfif arrayLen(result) AND result.path EQ "level1.level2.level3">
<!--- do something --->
</cfif>
Conclusion
Haven't tested, but I believe either will be faster than using IsDefined() or a try-catch block. Has the advantage over XMLValidate() of not needing a DTD. And, even with a DTD, the node you want may be defined as optional, so it could still validate.
You could validate the XML against a DTD to make sure the document was in the right format. XmlParse() and XmlValidate() both take a DTD as a parameter.
<cfset validateResult = XmlValidate(myXmlDocument, myDTD)>
<cfif validateResult.status>
<!--- xml is valid continue processing --->
<cfelse>
<!--- xml did not validate handle the error --->
</cfif>
Personally I wouldn't go crazy checking for every level of a 'deep' structure like this. I would presume that if the top level exists the rest of the document will be as you expect, and I'd just address the document from there.
If you wanted you could perhaps try to address the value in your struct and wrap it in a try/catch. That way you can handle any errors at any 'level' in the same way.
<cftry>
<cfset myVar = myStruct.level1.level2.level3 />
<cfcatch type="any">
<!--- Handle error --->
</cfcatch>
</cftry>
Hope that helps some.
I know I'm going to get booed off the stage here, but this is where isDefined() can save you a lot of typing:
<cfif isDefined(structKeyExists(myStruct.level1.level2.level3)>
<!--- do something --->
</cfif>
I know this is a year old, but I'm going to put in an answer here. I struggled for a good long time with this one, till I found a simple solution. If I know the structure of the XML already, a simple IsDefined works to test if the node or node attribute exists. I don't think most people know you can do this, or have tried and failed because they didn't include single quotes in the IsDefined function.
So say I grab some user xml from a web service somewhere and want to display the user's ID.
<cfhttp url="https://mycompany.com/mywebservices/getusers" username="me" password="mysecret">
<cfset userXMLDoc = XMLParse(ToString(cfhttp.FileContent).trim())>
<cfif IsDefined('userXMLDoc.Data.Record.User.XmlAttributes.id')>
<cfdump var="#userXMLDoc.Data.Record.User.XmlAttributes.id#">
<cfelse>
<cfoutput>Failed: No User ID found</cfoutput>
</cfif>
Im editing my first ColdFusion script .... I have a form which has <input type="hidden" name="name" value="1">.
On the processing page i want to take that value and set it as a POST variable so i can send it onto another page.
I know how to do it in PHP, like so
$_POST['somename'] = $_POST['name']
How would i do that in CF?
Following the idiom in your php code, you can do something like this:
<cfset form['somename'] = form['name']>
...or, if in cfscript:
form['somename'] = form['name'];
If you're concerned about the existence of the variable, you can precede the assignment with <cfparam>:
<cfparam name="form.name" default=""><!--- assuming blank ok as default --->
<cfset form['somename'] = form['name']>
...or in script:
param name='form.name' default='';
form['somename'] = form['name'];
Of course you can also wrap the assignment in a conditional:
if( structkeyexists(form,'name') ){
form.somename = form.name; // dot notation alternative to bracket syntax
}
This all begs the question of what exactly you're trying to achieve with this approach.
The ColdFusion syntax is similar. "Post" variables are available in the system structure FORM, and "Get" variables in the system structure URL. Like in PHP, values can be accessed using associative array notation. You can also use dot notation (for valid field names)
<cfset otherVariable = FORM["variableName"] >
<cfset otherVariable = FORM.variableName >
i want to take that value and set it
as a POST variable so i can send it
onto another page.
I am not quite sure what you mean there. Typically, you do not need to reassign FORM or URL values. You simply reference the variable in your code.
<cfoutput>
Go To Other Page
</cfoutput>
You can try this by checking if the post variable is set and then storing it with scope of FORM.
<cfif isdefined ("FORM.name")>
<cfset FORM.somename="#FORM.name#">
</cfif>