Coldfusion 从动态表单复选框创建数组
Coldfusion create array from dynamic form checkboxes
我有一个带有多个复选框的动态表单,在提交时我想 运行 在另一个 cfloop
中 CFSTOREDPROC
仅使用更改状态的复选框值。
到目前为止,下面是我正在尝试测试的一个粗略概念,但我确信我创建数组的方式会有问题。如果有人可以就可能的解决方案提供反馈,我将不胜感激。
HTML/CF 表格:
<form action="self.cfm" method="post" name="permissions">
<input type="hidden" name="User_ID" value="<CFOUTPUT>#User_ID#</CFOUTPUT>">
<table>
<CFLOOP QUERY="getNthPermission">
<tr><td>#getNthPermission.Permission_Name#</td><td><input type="checkbox" value="#getNthPermission.Permission_ID#" name="#getNthPermission.Permission_Name#" <CFIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) NEQ 0>CHECKED</CFIF>></td></tr>
</CFLOOP>
</table>
<input type="submit" name="submit" value="Update">
</form>
冷熔动作:
<CFSET VARIABLES.Permission_ID_List = ValueList(getUserPermission.Permission_ID)>
<cfset changed_permissions=ArrayNew()>
<CFLOOP QUERY="getNthPermission">
//If it was checked when the form was created but was unchecked by the user add it to my array.
<CFIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) NEQ 0 AND !IsDefined(FORM.#getNthPermission.Permission_Name#)>
<cfset changed_permissions[getNthPermission.Permission_ID]>
<CFELSEIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) EQ 0 AND IsDefined(FORM.#getNthPermission.Permission_Name#)>
//If it wasn't checked when the form was built but was checked by the user add it to my array.
<cfset changed_permissions[getNthPermission.Permission_ID]>
</CFIF>
</CFLOOP>
//现在遍历刚刚创建的数组,并将我的值传递给存储过程
<CFLOOP from="1" to="#arrayLen(changed_permissions)#" index="i">
<CFSTOREDPROC DATASOURCE="#MYDB_DSN#" PROCEDURE="Update_UserPermission">
<CFPROCPARAM DBVARNAME="@PermissionList" VALUE="#changed_permissions[i]#" TYPE="IN" CFSQLTYPE="cf_sql_longvarchar">
<CFPROCPARAM DBVARNAME="@User_ID" VALUE="#FORM.User_ID#" CFSQLTYPE="cf_sql_integer">
</CFSTOREDPROC>
</CFLOOP>
更新:
我正在使用我未参与设置的数据库配置,其中包含这些 table:
- 权限table (permission_name, ID) - 权限列表
- 用户table(user_name,ID)
- User_Permissions table (Permissions_ID, User_ID) - 包含用户有权访问的每个权限的条目。
因为复选框是 selected/unselected,所以我要么添加一个新条目,要么删除一个条目。已经存在的存储过程可以做到(或者我希望它可以做到)。
三个 tables 是一个很好的设置。我担心它是单个 table 或者值存储为 csv 列表 {shudder}。仍然无法很好地可视化您的表单,但是..从您的描述来看,通过一些查询而不是循环来执行此操作听起来会更简单。
首先,为复选框指定与 "Permission_IDList" 相同的名称,这样 id 将作为列表提交。然后将该 ID 列表与以下选项之一一起使用:
选项 1:删除/插入全部
我经常使用简单 junction tables 的一种方法是首先删除所有现有的用户权限。然后使用 INSERT/SELECT 插入 new 权限。使用 INSERT/SELECT 的两大优点是它消除了循环的需要,并且还提供了内置验证。
这是最简单的选项之一,但不如选项 2 精确,因为它每次都会删除所有记录。因此,从技术上讲,在许多情况下,它可能会比需要做更多的工作。尽管除非您处理大量记录,否则差异通常可以忽略不计。这些方面的东西(未测试):
--- First remove all existing permissions for User
DELETE FROM User_Permissions
WHERE User_ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
--- Now re-insert current/new permissions
INSERT INTO User_Permissions ( User_ID, Permissions_ID )
SELECT u.ID AS User_ID
, p.ID AS Permissions_ID
FROM UserTable u CROSS JOIN PermissionTable p
WHERE u.ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
AND p.ID IN
(
<cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
)
选项 2:DELETE 已更改/INSERT 添加
另一种选择是使用查询来识别和删除已删除(即未选中)的权限。然后使用 INSERT/SELECT 插入添加的权限。其余保持不变。它比选项 1 稍微复杂一点,但更精确,因为它只删除或添加实际更改的内容。同样,未经测试,但类似这样:
--- existing id's NOT in the new list were UN-checked
DELETE FROM User_Permissions
WHERE User_ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
AND Permissions_ID NOT IN
(
<cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
)
INSERT INTO UserPermissions ( User_ID, Permissions_ID )
SELECT u.ID AS User_ID
, p.ID AS Permissions_ID
FROM UserTable u
CROSS JOIN PermissionsTable p
LEFT JOIN UserPermissions up ON up.User_ID = u.ID AND up.Permissions_ID = p.ID
--- this user + permission does not already exist
WHERE up.Permissions_ID IS NULL
AND u.ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
AND p.ID IN
(
<cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
)
注意: 确保将两个查询包装在一个事务中,以便将它们视为一个单元,即要么都成功,要么都失败。
我有一个带有多个复选框的动态表单,在提交时我想 运行 在另一个 cfloop
中 CFSTOREDPROC
仅使用更改状态的复选框值。
到目前为止,下面是我正在尝试测试的一个粗略概念,但我确信我创建数组的方式会有问题。如果有人可以就可能的解决方案提供反馈,我将不胜感激。
HTML/CF 表格:
<form action="self.cfm" method="post" name="permissions">
<input type="hidden" name="User_ID" value="<CFOUTPUT>#User_ID#</CFOUTPUT>">
<table>
<CFLOOP QUERY="getNthPermission">
<tr><td>#getNthPermission.Permission_Name#</td><td><input type="checkbox" value="#getNthPermission.Permission_ID#" name="#getNthPermission.Permission_Name#" <CFIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) NEQ 0>CHECKED</CFIF>></td></tr>
</CFLOOP>
</table>
<input type="submit" name="submit" value="Update">
</form>
冷熔动作:
<CFSET VARIABLES.Permission_ID_List = ValueList(getUserPermission.Permission_ID)>
<cfset changed_permissions=ArrayNew()>
<CFLOOP QUERY="getNthPermission">
//If it was checked when the form was created but was unchecked by the user add it to my array.
<CFIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) NEQ 0 AND !IsDefined(FORM.#getNthPermission.Permission_Name#)>
<cfset changed_permissions[getNthPermission.Permission_ID]>
<CFELSEIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) EQ 0 AND IsDefined(FORM.#getNthPermission.Permission_Name#)>
//If it wasn't checked when the form was built but was checked by the user add it to my array.
<cfset changed_permissions[getNthPermission.Permission_ID]>
</CFIF>
</CFLOOP>
//现在遍历刚刚创建的数组,并将我的值传递给存储过程
<CFLOOP from="1" to="#arrayLen(changed_permissions)#" index="i">
<CFSTOREDPROC DATASOURCE="#MYDB_DSN#" PROCEDURE="Update_UserPermission">
<CFPROCPARAM DBVARNAME="@PermissionList" VALUE="#changed_permissions[i]#" TYPE="IN" CFSQLTYPE="cf_sql_longvarchar">
<CFPROCPARAM DBVARNAME="@User_ID" VALUE="#FORM.User_ID#" CFSQLTYPE="cf_sql_integer">
</CFSTOREDPROC>
</CFLOOP>
更新:
我正在使用我未参与设置的数据库配置,其中包含这些 table:
- 权限table (permission_name, ID) - 权限列表
- 用户table(user_name,ID)
- User_Permissions table (Permissions_ID, User_ID) - 包含用户有权访问的每个权限的条目。
因为复选框是 selected/unselected,所以我要么添加一个新条目,要么删除一个条目。已经存在的存储过程可以做到(或者我希望它可以做到)。
三个 tables 是一个很好的设置。我担心它是单个 table 或者值存储为 csv 列表 {shudder}。仍然无法很好地可视化您的表单,但是..从您的描述来看,通过一些查询而不是循环来执行此操作听起来会更简单。
首先,为复选框指定与 "Permission_IDList" 相同的名称,这样 id 将作为列表提交。然后将该 ID 列表与以下选项之一一起使用:
选项 1:删除/插入全部
我经常使用简单 junction tables 的一种方法是首先删除所有现有的用户权限。然后使用 INSERT/SELECT 插入 new 权限。使用 INSERT/SELECT 的两大优点是它消除了循环的需要,并且还提供了内置验证。
这是最简单的选项之一,但不如选项 2 精确,因为它每次都会删除所有记录。因此,从技术上讲,在许多情况下,它可能会比需要做更多的工作。尽管除非您处理大量记录,否则差异通常可以忽略不计。这些方面的东西(未测试):
--- First remove all existing permissions for User
DELETE FROM User_Permissions
WHERE User_ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
--- Now re-insert current/new permissions
INSERT INTO User_Permissions ( User_ID, Permissions_ID )
SELECT u.ID AS User_ID
, p.ID AS Permissions_ID
FROM UserTable u CROSS JOIN PermissionTable p
WHERE u.ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
AND p.ID IN
(
<cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
)
选项 2:DELETE 已更改/INSERT 添加
另一种选择是使用查询来识别和删除已删除(即未选中)的权限。然后使用 INSERT/SELECT 插入添加的权限。其余保持不变。它比选项 1 稍微复杂一点,但更精确,因为它只删除或添加实际更改的内容。同样,未经测试,但类似这样:
--- existing id's NOT in the new list were UN-checked
DELETE FROM User_Permissions
WHERE User_ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
AND Permissions_ID NOT IN
(
<cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
)
INSERT INTO UserPermissions ( User_ID, Permissions_ID )
SELECT u.ID AS User_ID
, p.ID AS Permissions_ID
FROM UserTable u
CROSS JOIN PermissionsTable p
LEFT JOIN UserPermissions up ON up.User_ID = u.ID AND up.Permissions_ID = p.ID
--- this user + permission does not already exist
WHERE up.Permissions_ID IS NULL
AND u.ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
AND p.ID IN
(
<cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
)
注意: 确保将两个查询包装在一个事务中,以便将它们视为一个单元,即要么都成功,要么都失败。