SQL查询内部联接表,打印到HTML <select>标记

格林达里

我的任务是更新旧的应用程序,然后遇到了麻烦。该应用程序在带有MySQL 5数据库的Railo(ColdFusion)上运行。

该应用程序正在使用基于角色的身份验证来管理用户。以前的开发人员似乎没有修改/添加/删除用户的代码,而只是直接修改了数据库列。我已经处理了添加/删除用户部分,没问题。修改部分是我偶然发现的地方。

下面是角色和成员的基本表布局。

MEMBERS TABLE
id | username | role
 1 | user1    | Administrator,User,Group1,Group2
 2 | user2    | User,Developer
 3 | user3    | SuperUser,Group1,Group2
 4 | user4    | SuperUser,Developer
 5 | user5    | Guest

ROLES TABLE
role_id | role_name
      1 | Administrator
      2 | Developer
      3 | SuperUser
      4 | Guest
      5 | User
      6 | Group1
      7 | Group2

要修改用户的角色,我的第一个想法是使用一个简单的HTML select标签和几个CFQUERY。类似于下面的代码。

<select name="role" multiple="multiple" size="7">
<cfoutput>
<option value="#GetRole.role_name#" <cfif GetRole.role_name = GetUser.role>checked</cfif>>#GetRole.role_name#</option>
</cfoutput>
</select>
<CFQUERY NAME="GetRole" DATASOURCE="#request.dataSource#">
  SELECT role_name
  FROM roles
</CFQUERY>

<CFQUERY NAME="GetUser" DATASOURCE="#request.dataSource#">
  SELECT a.id, a.username, a.role, b.role_name
  FROM members a
  LEFT JOIN roles b ON b.role_name = a.role
  WHERE a.id = #FORM.id#
</CFQUERY>

select标签将从GetRole中提取并填充所有可用角色。GetUser查询将从成员表中的列表中查找用户是其当前成员的角色。然后,我只需在select标签中使用“ checked”标志。那是我碰壁的地方。不管我走什么路,我都会不断进入数组以列出问题。

当我添加一个新用户时,我只使用“ role ='#ListQualify(FORM.role,”“)#',它将所有角色添加到我的select标记中,添加一个逗号,然后将它们吐入members.role列。

我什至试图一步一步地创建一个数组:

<cfset roleArray = ArrayNew(1)>

<cfloop query = "GetUser">
<cfset temp = ArrayAppend(roleArray, "#role#")>
</cfloop>

<cfset roleList = ArrayToList(roleArray, ",")>

我也尝试做一个SQL FIND_IN_SET()。

无论我尝试什么,我都会将可怕的数组转换为布尔错误。

有什么建议吗?我应该尝试使用不同于HTML select标签的方法吗?有什么我忽略的东西吗?非常感激任何的帮助。

希望我很好地发布了这个问题,只有第二次在这里发布了问题。:D

- - - - - - - - - - 更新 - - - - - - - - - -

我想补充一点,该应用程序在整个站点上都使用IsUserInRole()来检查用户是否可以访问某些区域。例如:

 <cfif IsUserInRole("Administrator")>
 Do stuff here as an administrator.
 </cfif>

它还与多个组一起使用,ColdFusion会自动查找每个用逗号分隔的组:

<cfif IsUserInRole("Administrator,Group1,Group2")>

ColdFusion是否有更好的方法来管理角色?

--------------------更新#2 --------------------

我发现原始开发人员使用CFLOGIN来为用户设置角色。我听说过有关CFLOGIN的恐怖故事,是否应该改而改用更好的东西?而是在会话变量中设置用户角色?

<cfquery name="qryGetUserDetails" datasource="#request.datasource#">
SELECT *
FROM members
WHERE username = <cfqueryparam cfsqltype="cf_sql_varchar" value='#Trim(FORM.username)#'>
</cfquery>
<cflogin>
  <cfloginuser name="#FORM.username#" password="#FORM.password#" roles="#qryGetUserDetails.role#">
</cflogin>

注意到cfqueryparam吗?:DI迅速运用了我从你们那里学到的知识!:D

(评论太久了)

我什至试图一步一步地创建一个数组:

暂时忽略db结构,创建数组是浪费时间:)如果将角色存储为列表,那么您要做的就是获取列表,创建单个元素数组并将其再次转换回相同的列表。因此摆脱数组。这没有任何目的。

只需循环getRole查询并使用列表功能即可。Dan很好地说明了复选框,但我将使用您的原始代码更好地说明:

<select name="role" multiple="multiple" size="7">
   <cfoutput query="getRole">
      <option value="#getRole.role_name#" 
        <!--- if the current role is found in the list of user roles --->
        <cfif listFindNoCase(getUser.ListOfRoles, getRole.role_name)>
           selected
        </cfif>>
        #GetRole.role_name#
       </option>
   </cfoutput>
</select>

话虽如此,真正的问题是您的数据库结构。存储列表是其中的一件事情,它看起来会让生活变得更轻松,但是几乎总是会产生比它解决的问题更多的问题。例如,使用当前结构-您将如何识别具有“管理员”和“来宾”角色而不是“超级用户”角色的所有用户?

尽管有一些技巧可以解决存储列表的一些固有限制,但您应该尽可能地更改表结构。列表更容易出现数据完整性问题。另外,由于依赖于字符串函数,因此经常需要使用SQL索引的卷积SQL查询,因此无法很好地扩展。

正如我在评论中提到的,更好的结构是创建第三个表:MemberRole。将每个memberID + roleID组合存储为单独的行。该结构将提供更大的灵活性和可靠性。有关示例,请参见bricktsage的答案虽然可以稍微简化“编辑用户”查询的联接。为了清楚起见,我删除了一些逻辑。但是,正如原始帖子中提到的那样,出于安全原因,您可能需要添加其他过滤器来限制当前用户可以分配的角色。否则,任何用户都可以分配任何权限。

注意:我添加了一个布尔标志,希望在我的应用程序中使用。使用OUTER JOIN和CASE语句,您可以创建一个名为的布尔列IsAssigned,该指示是否将每个角色都分配给了所选用户。该标志可用于在编辑屏幕上预选列表项(或复选框)。

SELECT  ur.roleID
        , ur.roleTitle
        , ur.UserID
        , ur.UserName
        , CASE WHEN p.UserID IS NOT NULL THEN 1 ELSE 0 END AS IsAssigned
FROM   (
          SELECT u.UserID
                 , u.UserName
                 , r.RoleID
                 , r.RoleTitle
          FROM   Users u CROSS JOIN Roles r
          WHERE  u.UserID = <cfqueryparam value="#FORM.id#" cfsqltype="cf_sql_integer">

       ) 
       ur LEFT JOIN Permissions p
                ON p.RoleID = ur.RoleID
                AND p.UserID = ur.UserID

注意:请务必阅读CROSS JOIN

就是说,出于可读性考虑,我经常只运行两个查询:一个查询获取用户信息,另一个查询分配的角色。这是一个额外的db调用,但是回撤的数据略少,因此额外的查询并不是什么大问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

SQL查询内部联接表,打印到HTML <select>标记

来自分类Dev

使<select>标记选择显示HTML

来自分类Dev

Elm-Select标记内的Dynamic Html Option标记

来自分类Dev

HTML <select>标记中有多个值

来自分类Dev

html select标记:从另一个select标记中选择获取值

来自分类Dev

AngularJS <select> DOM标记

来自分类Dev

如何在多个SELECT输出中标记结果表

来自分类Dev

在select_tag中为<option>标记设置HTML选项

来自分类Dev

将<select> HTML标记中的选定值传递给JAVASCRIPT

来自分类Dev

HTML:当select标记包含功能时,请选择默认选项

来自分类Dev

带有 PHP MYSQL SELECT 查询的 HTML 选项标记导致标记后的所有内容不显示

来自分类Dev

伪元素和SELECT标记

来自分类Dev

伪元素和SELECT标记

来自分类Dev

HTML旁标记与div标记

来自分类Dev

SQL select语句内部联接

来自分类Dev

set_select用于代码标记中的选择标记

来自分类Dev

jQuery:在<select>标记内选择所有<option>标记

来自分类Dev

通过html select标记创建时如何获取UIPickerView的对象引用

来自分类Dev

使用HTML在select2标记生成器中设置maxElements属性

来自分类Dev

Select2可以正确显示粗体文本,但是键入时,粗体将成为html标记

来自分类Dev

如何在没有<form> HTML标记的情况下获取<select>的值

来自分类Dev

设置标记<select> html的值,该值来自php中的数据库

来自分类Dev

使用HTML在select2标记生成器中设置maxElements属性

来自分类Dev

如何在SELECT中标记表格?

来自分类Dev

jQuery-在<select>内添加<option>标记

来自分类Dev

XPath查询以获取<a>标记和<b>标记

来自分类Dev

XPath查询以获取<a>标记和<b>标记

来自分类Dev

<span>内部<form>标记

来自分类Dev

HTML标记添加了多余的<a>标记<divs>?

Related 相关文章

热门标签

归档