问题
I am building a form for my ColdFusion application using the naming format report[{field-name}] which when using RoR or CFWheels would give me a struct on the backend called report containing all of my field names. I am using FW/1 so all of my form fields get put into the RC scope rather than remaining in the Form scope. I know that it is possible to convert my form fields into a ColdFusion struct, because, as I said, CFWheels does it. I just have no idea how to make my application do it.
Here is part of the form that I am talking about
<dl class="oneColumn">
<dt class="first"><label for="report[name]">Name</label></dt>
<dd><input type="text" name="report[name]" class="text" /></dd>
<dt><label for="report[description]">Description</label></dt>
<dd><textarea name="report[description]" class="textarea"></textarea></dd>
</dl>
回答1:
Adam had the right context, but his code snippet was wrong.
A function that will work is this:
<cffunction name="$createNestedParamStruct" returntype="struct" access="public" output="false">
<cfargument name="params" type="struct" required="true" />
<cfscript>
var loc = {};
for(loc.key in arguments.params)
{
if (Find("[", loc.key) && Right(loc.key, 1) == "]")
{
// object form field
loc.name = SpanExcluding(loc.key, "[");
// we split the key into an array so the developer can have unlimited levels of params passed in
loc.nested = ListToArray(ReplaceList(loc.key, loc.name & "[,]", ""), "[", true);
if (!StructKeyExists(arguments.params, loc.name))
arguments.params[loc.name] = {};
loc.struct = arguments.params[loc.name]; // we need a reference to the struct so we can nest other structs if needed
loc.iEnd = ArrayLen(loc.nested);
for(loc.i = 1; loc.i lte loc.iEnd; loc.i++) // looping over the array allows for infinite nesting
{
loc.item = loc.nested[loc.i];
if (!StructKeyExists(loc.struct, loc.item))
loc.struct[loc.item] = {};
if (loc.i != loc.iEnd)
loc.struct = loc.struct[loc.item]; // pass the new reference (structs pass a reference instead of a copy) to the next iteration
else
loc.struct[loc.item] = arguments.params[loc.key];
}
// delete the original key so it doesn't show up in the params
StructDelete(arguments.params, loc.key, false);
}
}
</cfscript>
<cfreturn arguments.params />
</cffunction>
I tested it in my application (outside of CFWheels) and it worked perfectly. All you do is pass in a struct (in my case the Rc struct from FW/1) containing what should be structures, but displaying as strings and you will be returns a structure with nested structures.
Example:
<cfscript>
Struct['hello[world]'] = 1;
Struct['hello[earth]'] = 2;
myhello = $createNestedParamStruct(Struct);
/* Now myhello equals this:
myhello.hello.world = 1;
myhello.hello.eath = 2;
*/
</cfscript>
回答2:
So the most basic form of the change you need to do is this:
mystruct.name = form["report[name]"];
What you need to do is write a loop that loops over the form struct and parses the form field names and builds structures like these. I'm guessing it's already written somewhere in CFWheels (as a function), and you could save yourself headache and frustration by just finding it and pulling it out for yourself.
I think this is it, but I'm not sure:
<!--- helper method to recursively map a structure to build mapping paths and retrieve its values so you can have your way with a deeply nested structure --->
<cffunction name="$mapStruct" returntype="void" access="public" output="false" mixin="dispatch">
<cfargument name="map" type="struct" required="true" />
<cfargument name="struct" type="struct" required="true" />
<cfargument name="path" type="string" required="false" default="" />
<cfscript>
var loc = {};
for(loc.item in arguments.struct)
{
if (IsStruct(arguments.struct[loc.item])) // go further down the rabit hole
{
$mapStruct(map=arguments.map, struct=arguments.struct[loc.item], path="#arguments.path#[#loc.item#]");
}
else // map our position and value
{
arguments.map["#arguments.path#[#loc.item#]"] = {};
arguments.map["#arguments.path#[#loc.item#]"].value = arguments.struct[loc.item];
}
}
</cfscript>
</cffunction>
来源:https://stackoverflow.com/questions/5155929/coldfusion-converting-form-values-into-a-struct