这是我的问题。我有两个这样的表和一个PHP代码。
TABLES
menu
====
m_id menu_name parent_menu_id menu_order menu_url status
1 M1 0 1 # 1
2 M2 0 2 # 1
3 S1 1 1 # 1
4 S2 1 2 # 1
user_rights
===========
user_id rights
1 1,2,3,4
2 1,2,3
CODE
<?php
$get_user_id = $_GET['id']; // user id will be 1 or 2
mysql_connect("localhost", "root", "password") or die(mysql_error());
mysql_select_db("booksdb") or die(mysql_error());
$get_access_query = mysql_query("SELECT rights FROM user_rights where user_id='".$get_user_id."'");
$fetch_access_list = mysql_fetch_row($get_access_query);
$get_access_list = $fetch_access_list[0];
?>
<div id='mymenuclass'>
<ul>
<?php
foreach (explode(',', $get_access_list) as $n) {
$get_main_menu_query = mysql_query("SELECT * FROM menu where m_id='".$n."' and parent_menu_id='0' order by menu_order");
$get_main_menu = mysql_fetch_assoc($get_main_menu_query);
?>
<li class='has-sub'><a href='#'><span><?php echo $get_main_menu['menu_name']; ?></span></a>
<ul>
<?php
$get_sub_menu = mysql_query("SELECT * FROM menu_master where parent_menu_id='".$get_main_menu['m_id']."'");
while($row = mysql_fetch_assoc( $get_sub_menu )) {
?>
<li class='has-sub'><a href='<?php echo $row['menu_url']; ?>'><span><?php echo $row['menu_name']; ?></span></a></li>
<?php } ?>
</ul>
</li>
<?php } ?>
</ul>
</div>
以上查询适用于第一级菜单。但是当涉及子菜单时,它显示所有子菜单。不知道我哪里出错了。
例如:user_id = 2
仅允许访问菜单1,2和3.但我的上述代码允许1,2,3和4。
我如何限制它?
有任何帮助吗? 谢谢,
Kimz
注:
我的代码非常可怜。它会让像你这样的专家感到困惑。但我的要求在上面已经解释过了。帮助我,我可以奖励你;)
答案 0 :(得分:1)
您尝试使用php解决的问题实际上应该在数据库级别解决。 您将一组权限存储为纯文本。为什么? 现在,每当您需要检查某个菜单项的访问权限时,您需要获取所有权限,将其分解为数组,...昂贵。
因此,让我们在数据库级别解决这个问题。我们首先将所有内容写在人类可读的文本中。之后实施。
我们有一个用户(存储在表用户中)。每个用户都可以拥有零个或多个菜单访问权限。所以这是一个多对多的关系。 许多用户可以拥有许多菜单访问权限。
所以,我们有一个表users
,我们有一个表menu
和一个表menu_rights
(imo,menu_access是一个更好的名字)。
menu_rights
表将用户链接到某个menu.item
。这为menu_rights
表格user_id
和menu_id
所以现在,如果你想获得$ currentUser可以访问的所有menu_items,让数据库处理所有的逻辑,而不是在任何地方编写那个可怕的爆炸:
SELECT menu.* FROM menu,menu_rights WHERE menu.id = menu_rights.menu_id AND menu_rights.user_id = $current_user_id
现在,SQL处理所有te访问权限逻辑。整洁,因为SQL还跟踪所有访问权限。一个查询,用于检索您可以访问的所有菜单项。
然后,另一个说明。不要在生产中使用您的代码。只是不要。 以下是一些原因:
答案 1 :(得分:1)
首先,我建议规范化您的数据库,因为这些用户访问昏迷分离权限和菜单保存有问题。第二,停止使用mysql_ * lib(但是,在下面的例子中,我没有改变它),如Pinoniq所说。第三,不要弄乱HTML中的查询,因为它很容易在翻译中迷失,并且找不到问题。
现在,我在这里看到的问题是:
例如,您有以下架构:
用户ID:1 主菜单ID:1 儿童菜单ID:5 儿童菜单ID:8 儿童菜单ID:50 用户权限:1,8,50
您希望您的用户能够访问主菜单1但仅限于其子菜单8和50,而不是5
$get_main_menu_query = mysql_query("SELECT * FROM menu where m_id='".$n."' and parent_menu_id='0' order by menu_order");
这个会变成:
SELECT * FROM menu where m_id='1' and parent_menu_id='0' order by menu_order
SELECT * FROM menu where m_id='8' and parent_menu_id='0' order by menu_order
SELECT * FROM menu where m_id='50' and parent_menu_id='0' order by menu_order
由于8和50是CHILD MENU第二和第三个查询不会返回结果,因为parent_menu_id不是ZERO。只有第一个会返回结果。
后来
$get_sub_menu = mysql_query("SELECT * FROM menu_master where parent_menu_id='".$get_main_menu['m_id']."'");
将导致
SELECT * FROM menu_master where parent_menu_id=1
将返回三个结果:5,8和50,因为你没有告诉:`给我父母id 1的子菜单以及哪个用户有权利。
您需要返回检查权限的检查位置并应用AND id = "fetchedRecordsFromUserRights"
应该变成:
SELECT * FROM menu_master where parent_menu_id=1 AND id = 1; // 0 records
SELECT * FROM menu_master where parent_menu_id=1 AND id = 5; // 0 records because 5 is not in RIGHTS
SELECT * FROM menu_master where parent_menu_id=1 AND id = 8; // 1 record
SELECT * FROM menu_master where parent_menu_id=1 AND id = 50; // 1 more record
我将给你的以下代码试图通过拆分函数来做到这一点,因此你不需要两次获取权限。但是,我不保证它是完全可行的,因为我没有测试它,如果不是,你应该自己做,检查哪个函数返回错误的值。
请记住,您不需要数组中的RIGHTS。 MySQL有IN()
运算符,所以如果你已经获取字符串1, 8, 50
,你可以做
SELECT * FROM menu_master where parent_menu_id=1 AND id IN (1, 8, 50);
将返回2条记录,分别为8和50。
这是我为你重写的代码
<?php
$get_user_id = $_GET['id']; // user id will be 1 or 2
mysql_connect("localhost", "root", "password") or die(mysql_error());
mysql_select_db("booksdb") or die(mysql_error());
/**
*
* @param int $get_user_id
* @return string
*/
function getMenuRights($get_user_id) {
$get_user_id = intval($get_user_id);
$get_access_query = mysql_query("SELECT rights FROM user_rights where user_id='".$get_user_id."'");
$fetch_access_list = mysql_fetch_row($get_access_query);
$get_access_list = $fetch_access_list[0];
return $get_access_list;
}
/**
*
* @param int $get_user_id
* @return array
*/
function getUserMainMenus($get_user_id) {
$get_user_id = intval($get_user_id);
$rights = getMenuRights($get_user_id);
$get_main_menu_query = mysql_query("SELECT * FROM menu where m_id IN ($rights) and parent_menu_id='0' order by menu_order");
while ($row = mysql_fetch_assoc($get_main_menu_query)) {
$results[] = $row;
}
return $results;
}
/**
*
* @param int $parent_menu_id
* @param int $get_user_id
* @return array
*/
function getUserChildMenu($parent_menu_id, $get_user_id) {
$parent_menu_id = intval($parent_menu_id);
$get_user_id = intval($get_user_id);
$rights = getMenuRights($get_user_id);
$get_sub_menu = mysql_query("SELECT * FROM menu_master where parent_menu_id='".$parent_menu_id."' AND id IN ($rights)");
while($row = mysql_fetch_assoc( $get_sub_menu )) {
$results[] = $row;
}
return $results;
}
?>
<div id='mymenuclass'>
<ul>
<?php foreach (getUserMainMenus($get_user_id) as $get_main_menu): ?>
<li class='has-sub'><a href='#'><span><?=$get_main_menu['menu_name']; ?></span></a>
<ul>
<?php foreach (getUserChildMenu($get_main_menu['m_id'], $get_user_id) as $row): ?>
<li class='has-sub'><a href='<?=$row['menu_url']; ?>'><span><?=$row['menu_name']; ?></span></a></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
</div>
答案 2 :(得分:0)
作为已经提供的建议的替代方案,如果您知道只有少数“权利”,那么您可以按位方式存储这些:
privilege _id
1
2
4
8
在这种设计中,得分为3的用户将享受1和1的特权。 2,得分为15的用户将享有所有特权。