PHP MYSQL中菜单的用户访问权限

时间:2014-04-30 07:12:12

标签: php mysql loops for-loop drop-down-menu

这是我的问题。我有两个这样的表和一个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

注:

我的代码非常可怜。它会让像你这样的专家感到困惑。但我的要求在上面已经解释过了。帮助我,我可以奖励你;)

3 个答案:

答案 0 :(得分:1)

您尝试使用php解决的问题实际上应该在数据库级别解决。 您将一组权限存储为纯文本。为什么? 现在,每当您需要检查某个菜单项的访问权限时,您需要获取所有权限,将其分解为数组,...昂贵。

因此,让我们在数据库级别解决这个问题。我们首先将所有内容写在人类可读的文本中。之后实施。

我们有一个用户(存储在表用户中)。每个用户都可以拥有零个或多个菜单访问权限。所以这是一个多对多的关系。 许多用户可以拥有许多菜单访问权限。

所以,我们有一个表users,我们有一个表menu和一个表menu_rights(imo,menu_access是一个更好的名字)。

menu_rights表将用户链接到某个menu.item。这为menu_rights表格user_idmenu_id

提供了2列

所以现在,如果你想获得$ 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的用户将享有所有特权。