cfquery name attribute, optional? - coldfusion

Is name attribute of cfquery optional? The doc said it is required, but my code seems to run fine even without it. Is there a default value if not defined? and if so, shall I local var it or safely ignore it?
Thx

I think you can safely omit the name. It does not appear to add a default name to the variables or local scopes.
However, I did notice something strange under CF9. If you do not local scope the result, the key cfquery.executiontime is added to the variables scope. This is with all debugging disabled (unless I missed something).
Results:
Before Variables = 1 Local = 1
After Variables = 2 Local = 1 (result NOT local scoped)
<cffunction name="myFunction" output="true">
<b>Before</b>
Variables = #structCount(variables)#
Local = #structCount(local)#<br />
<cfquery datasource="MyDatasource">
SELECT getDate() AS TestDate
</cfquery>
<b>After</b>
Variables = #structCount(variables)#
Local = #structCount(local)#<br />
</cffunction>

The name attribute is required, but I just tested it & it does not throw an error if the name attribute is missing... how very interesting. Though, without the name attribute - how are you going to get at the result set?
What an interesting question.
UPDATE
Just ran a quick test and did some googling:
<cfquery datasource="#dsn#" result="qresult">
select some_stuff from that_table limit a_bunch
</cfquery>
<cfdump var="#qresult#" />
Dumping the result attribute shows clearly that the query has run and did get a result set - though there appears to be no way to access it.
Googling & docs were no help with the defaults or scope.. maybe ping these guys: http://www.bennadel.com/ - I run across a lot of 'experimenting' on their site.
Now the docs do say that the name attribute is required, but I guess I can see situations where it may not be necessary - obviously memory isn't used by the name variable not being there, but what about the result set? so I'm guessing if you run any query where you don't actually need info back from it [anything but a select?] you can get all the info you need by using the result attribute and MAYBE save some memory and execution time?
isn't that a fun thought?
-sean

Related

Issues with Application Scope for fetching the CFC's

I am trying to get the CFC linked but i am getting an error:
Here is my Configration in my Application.cfc
<cfset Application.relativePath = "/">
<cfset Application.componentsPath = Replace(Application.relativePath,"/","",'All')>
<cfset Application.cfcpath = Application.componentsPath & "com">
<cfset Application.tools = '#Application.cfcpath#.tools'>
Now when i acces the cfc from my page like this:
<cfset result = Application.cfcpath.tools.saveDrivers(form)>
I am getting an Error:
Element CFCPATH.TOOLS is undefined in a Java object of type class [Ljava.lang.String; referenced as ''
if i try
<cfset result = Application.tools.saveDrivers(form)>
I get an Error:
The saveDrivers method was not found.
Either there are no methods with the specified method name and argument types or the saveDrivers method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that match the provided arguments. If this is a Java object and you verified that the method exists, use the javacast function to reduce ambiguity.
I dumped out the Application Scope and all seems ok, but i am not sure what is troubling here
Both Application.cfcpath and Application.tools are just strings, so can only be used as strings; whereas Application.cfcpath.tools within the statement:
<cfset result = Application.cfcpath.tools.saveDrivers(form)>
is a variable reference. You can't have a string holding a variable reference and hope that somehow ColdFusion will magically equate the two.
It's unclear from your question whether you are trying to create an object with your statement, or are simply referencing an existing one. I suspect it's the former. In which case, you want this sort of thing, I think:
tools = createObject(Application.tools);

Cfhttp result struct behaves as if null in CF8?

I'm trying to do some sanitation on the results of a call to Facebook but Coldfusion is telling me that the variable is null:
FILECONTENT null <br>The error occurred on line 66.
Here's the line that causes the error:
<cfif isDefined("storeFeedJSON.fileContent")>
<cfset storeFeedJSON.fileContent = process.CleanBadUnicode("#storeFeedJSON.fileContent#")>
</cfif>
The struct is clearly not null however as I have it wrapped in an "isDefined" and when I dump storeFeedJSON I can see fileContent looks like
{"data":[]}
Empty JSON but still not null...
EDIT: Here's the call I forgot to put in there:
<cfset fbURL = "https://graph.facebook.com/#qStoreFBPages.pageID#/#fbEdge#?fields=#fbFields#&since=#fbSinceTime#&#qToken.objectValue#">
<cfhttp result="storeFeedJSON" url="#fbURL#" method="get"></cfhttp>
which would probably end up looking something like this:
<cfhttp result="storeFeedJSON" url="https://graph.facebook.com/1749383765/posts?fields=created_time&since=1389296713&access_token=CAAH6oehQqUUU2IALvt0ZB3mdE6E2LCaldFc1TjIqxALUZBMqZC01O2hQXkOX8ROI9QBHn7WjWrHHneazAP4gWbj0MBsRUlel9TAG52kjBm0bBOUHVEFmEusEUHfhznlqzH1GMgCpCU4z4SmgXU8oFZBPDyAv1ByJu167jgkVd6UROWtDZBNBCP&expires=5184000" method="get"></cfhttp>
Note that will not result in a valid response from Facebook as I've changed my token and some other params.
I don't think you can re-assign the properties of the storeFeedJSON struct.
storeFeedJSON is the result of your cfhttp, right? as in
<cfhttp url="xyz" result="storeFeedJSON">
... which I think is a protected or immutable data structure. You can obviously pass it as an argument for your function, but put the output in some other variable, or perhaps straight to the json deserialize.
<cfset local.cleanFileContent = process.CleanBadUnicode(storeFeedJSON.fileContent)>
<cfdump var="#deserializeJSON(local.cleanFileContent)#">
... and while I'm at it, you might want to use getasbinary="never" because Facebook may someday give you binary data, or change its headers or something, and then your code will break. If you have to receive binary, you'll need cfhttp.fileContent.toString() or something like that.

Connect to LDAP via ColdFusion

I am trying to get the following connection to our LDAP working via ColdFusion, however, I can never get it to return any values (i.e. results.recordcount always equals 0). I assume my problem is with the "start" portion of the query so I did some research and have tried numerous values but nothing seems to work.
<cfldap
server = "adserver"
action = "query"
username = "DOMAIN\username"
password = "apassword"
name = "results"
scope="subtree"
start = "dc=domain.local"
attributes = "givenname,surname,uid,userid,groupMembership,mail,dn,roles,memberof,cn,samaccountName">
<cfoutput>
#results.recordcount#
</cfoutput>
The structure of the AD that I'm trying to access is as follows. I'm trying to get to the "Users" section at the bottom of the tree shown.
Active Directory Users and Computers
- Saved queries
- domain.local
- option1
- option2
- NAME1
- option1
- option2
- NAME2
- Computers
- Disabled Users
- Groups
- Users
If I right-click on "User" and view the properties it tells me the canonical name for it is domain.local/NAME1/NAME2/Users, which I assume is relevant to my problem.
Any ideas what I should be using for the "start" portion of cfldap?
Thanks in advance.
I highly recommend browsing your AD with a program like Softerra's LDAP Browser (http://www.ldapbrowser.com/) and then locating the distinguished name of the hierarchy where you want to start searching. Using this, I was able to find the exact DN of the LDAP structure to target.
Try somethign like this. I've had the best luck starting at a high level and then using the filter attribute to drill down.
<cfldap action="query" start="DC=server, DC=domain, DC=com" filter="OU=Users"
username = "DOMAIN\username" password = "apassword" name = "results"
scope="subtree" attributes = "givenname,surname,uid,userid,groupMembership,mail,dn,roles,memberof,cn,samaccountName">

update() and save() methods result in "no matching method/function" in railo

I'm trying to run a very quick update query to record that a user's email address is confirmed (setting the confirmed [bit] column in my users table to 1 after they click a link sent via email). Here's the action that should do it:
<cffunction name="confirmEmail">
<cfscript>
user = model("user").findOne(where="id=#params.userid# AND uuid='#params.uuid#'", returnAs="query");
if(user.recordCount) {
pageTitle = "E-mail Confirmation Success";
user.update(confirmed=1);
} else {
redirectTo(route="authenticationDenied", alert="Something was wrong with your confirmation string. Please contact site administrators.");
}
</cfscript>
</cffunction>
But when I submit the appropriate URL (I've dumped and can see the model call finds one valid record), I get the following error in Railo 3.3.x:
No matching Method/Function [update] for call with named arguments found
...highlighting the user.update(confirmed=1); line in my code. So what am I doing wrong? Previously I have always used save/update(params.user) or thereabouts for these queries, but that seems like overkill here; I just want to pass a 1-bit update.
Okay, my CTO who is new to CFML and Wheels figured this out in like 5 seconds. Hence the "C" I guess.
By returning the user model as a query instead of an object, I didn't have access to the update/save() methods. (Duh, MVC n00b.) The reason I was returning it as a query was simply that I've been doing that a fair bit in order to have easy manipulation of output, and in this case so that I can test for the existence of a record the way I always have (if recordCount). But this works...
<cffunction name="confirmEmail">
<cfscript>
user = model("user").findOne(where="id=#params.userid# AND uuid='#params.uuid#'");
if(isObject(user)) {
user.update(confirmed="1");
} else {
flashInsert(error="Something was wrong with your confirmation string. Please contact site administrators.");
redirectTo(route="authenticationDenied");
}
</cfscript>
</cffunction>

cfwheels - updating nested properties with a composite key table

I'm trying to get a better setup working for updating a model with nested properties.
Right now in my edit view I define the textFieldTag manually to create the params struct by setting up the name as "myModel[myNestedProperty][#modelID#,#key2id#][name]"
in update action...
if I just use myModel.update(params.myModel) I can't get the update to work if there are any elements that require deletion
so I destroy all the models of the nested property that have the same id as myModel, in which case it works.
The downside is that if the update fails, the nested properties are all gone.
I've tried grabbing all of the models first before deleting them and .saveing them, but for some reason that's not working.
Looks like cfwheel is setup for this kind of relation with the checkboxes, but I need it to work with textfield and select items in my form.
Update
I realized I have another issue. Essentially I would like to expand on this to be able to use it across multiple nested properties and relationships.
the issue is in the way I setup the name especially for select dropdowns:
name="myModel[myNestedProperty][#modelID#, ][nestedID]"
the issue is that the second id cannot be declared, because it will be assigned as the id rather than using the value that I select.
To be honest, this is the one issue I've been battling with my whole time. I'm dealing with it by regenerating the models in the controller, I just forgot I haven't solved that issue yet.
Is there a way I can have these values not be used at all, and have them populated from the structure dynamically?
let's say I have (truncated) a name tcat[34,0][catID] or tcat[34,][catID], (where the catID should be the 2nd ID).
the params' tcat structure that gets generated is
[34,0]{catID = 12,14,18}
or
[34,]{catID = 12,14,18}
I'd like the params' tcat structure to have multiple structs like:
[34,12]{tID = 34; catID = 12}
[34,14]{tID = 34; catID = 14}
[34,18]{tID = 34; catID = 18}
Is there a way around this?
I'm working with a lot of composite key nested properties, and if I could have this part alone working it would make it a lot easier. I know one way is to update the name with javascript, but I think that would be the (very,very) last resort.
Can you give this a try?
Set up a callback in the parent model that checks to see if name is blank and flags for deletion if it's blank.
<cffunction name="init">
...
<!--- This could also be `beforeValidation` if you want to make `name` required for the child model --->
<cfset beforeSave("$provisionMyNestedProperty")>
</cffunction>
<cffunction name="$provisionMyNestedProperty">
<cfscript>
if (StructKeyExists(this, "myNestedProperty") && IsArray(this.myNestedProperty))
{
for (local.i = 1; local.i <= ArrayLen(this.myNestedProperty); local.i++)
{
if (!StructKeyExists(this.myNestedProperty[local.i], "name") || !Len(Trim(this.myNestedProperty[local.i].name)))
this.myNestedProperty[local.i]._delete = true;
}
}
</cfscript>
</cffunction>
I'll keep editing my answer until we can bang out a solution. Hopefully that gives you a good start though.