3

まず、mysqlクエリで使用されるテーブル間の関係の図を示します。

テーブルの関係
(出典:r717.net

次のようなクエリがあります。

SELECT  * 
FROM    `permissions`
WHERE   `id` IN (
    SELECT      pr.perm_id 
    FROM        `user_roles` as ur 
    LEFT JOIN   `permissions_role` as pr 
    ON          ur.role_id = pr.role_id
    WHERE       ur.user_id = '$userid'
)
OR      `id` IN (
    SELECT      `perm_id` 
    FROM        `permissions_user` 
    WHERE       `user_id` = '$userid'
)

$userid現在のユーザーのユーザーテーブルのIDです。結果のアクセス許可名を、ユーザーの役割とIDに基づいてユーザーに割り当てられたすべてのアクセス許可を表す配列に格納します。

<?php
$user_perms = array();
if(mysql_num_rows($query) > 0):
    while($result = mysql_fetch_array($query):
        $user_perms[] = $result('name');
    endwhile;
endif;
?>

print_r($user_perms);次のような出力を生成します。

Array ( 
    [0] => ACCESS_TELEPHONELIST_PAGE
    [1] => ACCESS_VACATIONSCHED_PAGE
    [2] => ACCESS_TOURSCHED_PAGE
    [3] => ACCESS_WORKSCHED_PAGE
    [4] => ACCESS_RESOURCES_LINKS
    [5] => ACCESS_PMTOOL_PAGE
    [6] => ACCESS_TOOLSTOOL_PAGE
    [7] => ACCESS_SHOPTOOLLIST_PAGE
    [8] => ACCESS_TOOLINVENTORY_PAGE
    [9] => ACCESS_MANAGETOOLLIST_PAGE
    [10] => ACCESS_TOOLREPORTS_PAGE
    [11] => ACCESS_JOBSLIST_LINKS
    [12] => MAIN_TAB_TOOLSTOOL
    [13] => ADMIN_TAB_PODMANAGEMENT
    [14] => TOOL_TAB_SHOPTOOLLIST
)

私がやりたいのは、2番目のクエリを実行せずに、すべてのユーザーの役割を別の配列に格納することですサブクエリにエイリアスを使用する必要があると思ったので、次のクエリを試しました。

SELECT      permissions.*, usersroles.role_id 
FROM        `permissions`
INNER JOIN  (
    SELECT      ur.user_id, pr.perm_id, ur.role_id
    FROM        `user_roles` as ur
    LEFT JOIN   `permissions_role` as pr 
    ON          ur.role_id = pr.role_id
    WHERE       ur.user_id = '$userid'
) AS usersroles ON usersroles.perm_id = permissions.id
INNER JOIN  (
    SELECT      `perm_id`, `user_id` 
    FROM        `permissions_user` 
    WHERE       `user_id` = '$userid'
) AS userperms ON userperms.user_id = usersroles.user_id
              AND userperms.perm_id = permissions.id

そして、上記のコードと同様のコードを使用して...

<?php
$user_perms = array();
$user_roles = array();
if(mysql_num_rows($query) > 0):
    while($result = mysql_fetch_array($query):
        $user_perms = $result('name');
        $user_roles = $result('role_id');
    endwhile;
endif;
?>

...この警告が表示されます:

Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given

しかし、私はprint_r($user_roles);次のような出力を作成したいと思います。

Array (
    [0] => administrator
    [1] => humanresources
    [2] => podmanager
)

誰かが私が間違っていることを教えてもらえますか、または1つのクエリから2つの配列に必要なデータを取得するためのより良い方法を提案できます

編集:慎重に検討した後、ImreLが提案したように2つのクエリを使用するようにコードを変更しました。結果のコードはうまく機能し、すばやく実行されます。回答を編集して、使用した最終的なコードを表示し、2つのクエリをどのように使用しているかを示すためのサポートコードを追加しました。ImreLに感謝します!

4

2 に答える 2

2

クエリは、ユーザーが読み込むすべてのページで実行する必要があり、30,000を超える権限と3,000の役割があります。クエリの数を最小限に抑えるために、一生懸命努力しています。また、オフィスのサーバーで7つのサイトをホストしていますが、サーバーは生成されたトラフィック量を処理できないようです(残念ながら、これを制御することはできません)。

あなたの意図は良いと思いますが、これをお話ししましょう。

「クエリ数」は、サイトのパフォーマンスを測定する正しい方法ではありません。

多くの場合、2つの単純なクエリは1つの複雑なものよりも少ないリソースを使用します。

また、サイトを高速化する他の方法があります。

  • 各リクエストでこれらすべての役割と権限をロードする必要があるかどうかを評価します。たぶん、必要な役割/許可だけを照会するだけで十分です。
  • 適切なインデックスを作成する
  • キャッシュ技術を利用して負荷を軽減する(サイトコンテンツ)

それで最後に、私は尋ねられたものを満たすためにクエリを考え出そうとしました:

select * from (
    select ur.role_id, p.*
    from user_roles ur 
    left join permissions_role pr on ur.role_id =  pr.role_id
    left join permissions p on p.id = pr.perm_id
    where ur.user_id = '$userid'
  union all
    select null as role_id, p.*
    from permissions_user pu
    join permissions p on p.id = pu.perm_id
    where pu.user_id = '$userid'
) sub
group by ifnull(name,role_id) -- group by to eliminate duplicates

しかし、これはパフォーマンスには良くありません。2つのクエリを使用する方がはるかに優れています。1つ目はユーザーのすべての権限を取得する

select p.* from permissions p
join permissions_role pr on pr.perm_id = p.id
join user_roles ur on ur.role_id =  pr.role_id and ur.user_id = '$userid'
union
select p.* from permissions p
join  permissions_user pu on pu.perm_id = p.id and pu.user_id = '$userid';

そして2番目にすべての役割を取得します。

于 2012-05-03T00:44:26.227 に答える
0

編集:これが最終的な作業クエリです。また、クエリがどのように使用されているかを他の人が確認するのに役立つかもしれないと思ったので、完全な説明が含まれています。

//build the array(s)
$userperms = array();
$userroles = array();
if(isset($_SESSION['userid'])):
    //get the userid
    $thisuserid = $_SESSION['userid'];
    //get the permissions for each of the user's roles
    $Cpermissions_role = mysql_query(" 
    SELECT      r.type, ur.user_id, pr.perm_id, ur.role_id, p.name
    FROM        user_roles ur
    LEFT JOIN   permissions_role pr ON ur.role_id = pr.role_id
    LEFT JOIN   roles r ON ur.role_id = r.id
    LEFT JOIN   permissions p ON p.id = pr.perm_id
    WHERE       ur.user_id = '$userid'") or die(mysql_error());
    //get the extra permissions for the user
    $Cpermissions_user = mysql_query("
    SELECT      pu.user_id, pu.perm_id, p.name
    FROM        permissions_user pu
    LEFT JOIN   permissions p ON p.id = pu.perm_id
    WHERE       pu.user_id = '$userid'") or die(mysql_error());
    //build an array of the user's roles & an array of the user's permissions
    if(mysql_num_rows($Cpermissions_role) > 0):
        while($Rpermissions_role = mysql_fetch_array($Cpermissions_role)):
            if(empty($userperms)):
                $userperms[] = $Rpermissions_role['name'];
            elseif(!in_array($Rpermissions_role['name'],$userperms)):
                $userperms[] = $Rpermissions_role['name'];
            endif;
            if(empty($userroles)):
                $userroles[] = $Rpermissions_role['type'];
            elseif(!in_array($Rpermissions_role['type'],$userroles)):
                $userroles[] = $Rpermissions_role['type'];
            endif;
        endwhile;
    endif;
    if(mysql_num_rows($Cpermissions_user) > 0):
        while($Rpermissions_user = mysql_fetch_array($Cpermissions_user)):
            if(empty($userperms)):
                $userperms[] = $Rpermissions_user['name'];
            elseif(!in_array($Rpermissions_user['name'],$userperms)):
                $userperms[] = $Rpermissions_user['name'];
            endif;
        endwhile;
    endif;
endif;
/**
 * Determines if the user has permission for the page or parts of page
 * @param string $perm the permission constant
 * @return boolean true if user has access, false if not
 */
function hasPermission($perm){
    global $userperms;
    if(empty($userperms)):
        return false;
    else:
        if(is_array($userperms)):
            if(in_array($perm,$userperms)):
                return true;
            else:
                return false;
            endif;
        else:
            if($perm == $userperms):
                return true;
            else:
                return false;
            endif;
        endif;
    endif;
}

次に、次の決定ステートメントを使用します。

if(hasPermission("ACCESS_HOME_PAGE")):
    //perform circus tricks here
endif;

したがって、これをprint_r($userperms);出力します。

Array ( 
    [0] => ACCESS_TELEPHONELIST_PAGE
    [1] => ACCESS_VACATIONSCHED_PAGE
    [2] => ACCESS_TOURSCHED_PAGE
    [3] => ACCESS_WORKSCHED_PAGE
    [4] => ACCESS_RESOURCES_LINKS
    [5] => ACCESS_PMTOOL_PAGE
    [6] => ACCESS_TOOLSTOOL_PAGE
    [7] => ACCESS_SHOPTOOLLIST_PAGE
    [8] => ACCESS_TOOLINVENTORY_PAGE
    [9] => ACCESS_MANAGETOOLLIST_PAGE
    [10] => ACCESS_TOOLREPORTS_PAGE
    [11] => ACCESS_JOBSLIST_LINKS
    [12] => MAIN_TAB_TOOLSTOOL
    [13] => ADMIN_TAB_PODMANAGEMENT
    [14] => TOOL_TAB_SHOPTOOLLIST
    [15] => ACCESS_HOME_PAGE
)

そして、これをprint_r($userroles);出力します:

Array ( 
    [0] => administrator
    [1] => humanresourcees
    [2] => podmanager
)

そして、念のため、php配列にアクセスするために使用するJavaScriptを次に示します。

var js_userperms = new Array();
js_userperms = ["<?php echo join("\", \"", $userperms); ?>"];

そして、jQueryの決定ステートメント:

if(jQuery.inArray("ACCESS_HOME_PAGE", js_userperms) != -1){
    //perform circus tricks here
}
于 2012-05-03T09:13:57.273 に答える