2016-03-02 59 views
2

我有一个动态表单,有多个复选框,并提交我想运行一个CFSTOREDPROC在另一个cfloop只使用改变状态的复选框值。Coldfusion从动态表单复选框创建数组

到目前为止,下面是一个粗略的概念,我试图测试,但我确信我创建我的数组的方式会有问题。如果任何人都可以提供可能的解决方案的反馈,我会感激。

HTML/CF FORM:

<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> 

COLDFUSION ACTION:

<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> 

更新:

我正与一个数据库配置工作,我是不设立,其中有这些表的一部分:

  • 权限表(PERMISSION_NAME,ID) - 权限名单
  • 用户表(USER_NAME ,ID)
  • User_Permissions表(Permissions_ID,User_ID) - 包含用户有权访问的每个权限的条目。

因此,作为复选框被选中/未选中我需要添加新条目或删除一个。哪一个已经存在的存储过程(或者我希望它存在)。

+1

它只是一组可以分配/取消分配给单个用户的权限吗?如果没有涉及到实际值的样本,那么很难直观地看到*精确*关系。另外,这些权限如何存储在数据库中,单独的行或作为csv列表(希望不是)? – Leigh

+0

不幸的是,我正在使用一个数据库配置,而我并不是设置的一部分。有一个包含权限列表(permission_name,ID)和用户表(user_name,ID)和User_Permissions表(Permissions_ID,User_ID)的表,其中包含用户有权访问的每个权限的条目。所以当复选框被选中/取消选中时,我可以添加一个新条目或删除一个。哪一个已经存在的存储过程(或者我希望它) – Denoteone

回答

3

三张桌子是一个很好的设置。我担心这是一个单独的表格,或者这些值被存储为csv列表{颤抖}。仍然不能很好地形象化你的表单,但是从你描述的内容来看,听起来像用几个查询来做这件事会更简单,而不是循环。

首先,给复选框相同的名称,如“Permission_IDList”,这样的ID将被作为一份名单。然后使用的ID的该列表与下列选项之一:

选项1:删除/插入ALL

的一种方法,我经常用简单的junction tables做法是先删除所有现有的用户权限。然后使用INSERT/SELECT插入新的权限。使用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:删除改变/ INSERT加入

另一种选择是使用查询来识别和DELETE卸下的权限,即,未选中。然后使用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"> 

     ) 

NB:一定要在一个事务来包装这两个查询,以便它们作为一个单元,即两个都成功,要么都失败处理。

+0

再次感谢Leigh提供的详细解决方案。两者都很合理,说实话,我很高兴摆脱循环。我将选择#1,因为我们只谈论少数权限,我并不担心影响性能。这是你今天帮助我的第二个节日。再次感谢! +1检查。 – Denoteone

+0

我对第一个选项如何通过每个权限运行没有使用循环有疑问吗?上述SQL是否被用作存储过程?感谢您的跟进.. – Denoteone

+0

等待几遍代码后,我看到这将如何工作。我现在会测试并让你知道结果。再次感谢。 – Denoteone