我为什么要在PHP中使用按位/位掩码?

Jas*_*vis 18 php bit-manipulation bitmask

我正在使用PHP的用户角色/权限系统来处理脚本.

下面是使用我在phpbuilder.com上找到的权限的位掩码方法的代码.

在那个部分下面是一个更简单的版本w3hich可以做基本相同的事情没有位部分.

许多人建议在PHP中使用位操作符等设置和其他东西,但我从来没有理解为什么.在下面的代码中,使用第一个代码而不是第二个代码有什么好处

<?php
/**
 * Correct the variables stored in array.
 * @param    integer    $mask Integer of the bit
 * @return    array
 */
function bitMask($mask = 0) {
    $return = array();
    while ($mask > 0) {
        for($i = 0, $n = 0; $i <= $mask; $i = 1 * pow(2, $n), $n++) {
            $end = $i;
        }
        $return[] = $end;
        $mask = $mask - $end;
    }
    sort($return);
    return $return;
}


define('PERMISSION_DENIED', 0);
define('PERMISSION_READ', 1);
define('PERMISSION_ADD',  2);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 8);

//run function
// this value would be pulled from a user's setting mysql table
$_ARR_permission = bitMask('5');

if(in_array(PERMISSION_READ, $_ARR_permission)) {
    echo 'Access granted.';
}else {
    echo 'Access denied.';
}
?>
Run Code Online (Sandbox Code Playgroud)

非位版本

<?PHP
/*
   NON bitwise method
*/

// this value would be pulled from a user's setting mysql table
$user_permission_level = 4;

if($user_permission_level === 4) {
    echo 'Access granted.';
}else {
    echo 'Access denied.';
}

?>
Run Code Online (Sandbox Code Playgroud)

Rik*_*ood 41

为什么不这样做......

define('PERMISSION_DENIED', 0);
define('PERMISSION_READ', 1);
define('PERMISSION_ADD',  2);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 8);

//run function
// this value would be pulled from a user's setting mysql table
$_ARR_permission = 5;

if($_ARR_permission & PERMISSION_READ) {
    echo 'Access granted.';
}else {
    echo 'Access denied.';
}
Run Code Online (Sandbox Code Playgroud)

如果使用位,您还可以创建许多任意权限组合...

$read_only = PERMISSION_READ;
$read_delete = PERMISSION_READ | PERMISSION_DELETE;
$full_rights = PERMISSION_DENIED | PERMISSION_READ | PERMISSION_ADD | PERMISSION_UPDATE | PERMISSION_DELETE;

//manipulating permissions is easy...
$myrights = PERMISSION_READ;
$myrights |= PERMISSION_UPDATE;    // add Update permission to my rights
Run Code Online (Sandbox Code Playgroud)

  • 这确实使用了这些位.它只是删除了你没有真正需要的所有代码.使用位的优点是每个权限都可以独立于所有其他权限(或不可用).例如,无论任何其他权限的设置如何,您都可以拥有读取权限. (2认同)

Dom*_*ger 10

第一个允许人们拥有许多权限 - 例如,读取/添加/更新.第二个例子,用户刚才PERMISSION_UPDATE.

按位测试通过测试真值的位来工作.

例如,二进制序列10010将识别具有PERMISSION_DELETE和的用户PERMISSION_READ(位识别PERMISSION_READ是2的列,位识别PERMISSION_DELETE是16的列),10010二进制是十进制的18(16 + 2 = 18).您的第二个代码示例不允许您进行此类测试.您可以进行大于样式检查,但假设每个人都PERMISSION_DELETE应该拥有PERMISSION_UPDATE,这可能不是一个有效的假设.


dav*_*nal 10

也许这只是因为我不经常使用bitmasks,但我发现在PHP这样的语言中,开发人员的工作效率和代码可读性比速度或内存使用更重要(显然在极限范围内),没有真正的理由使用bitmasking .

为什么不创建一个跟踪权限,登录用户等内容的类?我们称之为Auth.然后,如果要检查用户是否具有权限,则可以创建方法HasPermission.例如,

if(Auth::logged_in() && Auth::currentUser()->hasPermission('read'))
    //user can read
Run Code Online (Sandbox Code Playgroud)

然后,如果你想检查他们是否有一些权限组合:

if(Auth::logged_in() && Auth::currentUser()->hasAllPermissions('read', 'write'))
    //user can read, and write
Run Code Online (Sandbox Code Playgroud)

或者如果你想检查他们是否拥有任何一组权限:

if(Auth::logged_in() && Auth::currentUser()->hasAnyPermissions('read', 'write'))
    //user can read, or write
Run Code Online (Sandbox Code Playgroud)

当然,定义常量可能不是一个坏主意,例如PERMISSION_READ,您可以将其定义为字符串'read',依此类推.

我发现这种方法比bitmasks更容易阅读,因为方法名称可以准确地告诉您它正在寻找什么.

  • 使用类来隐藏实现总是一个好主意.您可以轻松拥有:Auth :: currentUser() - > hasAnyPerm(PERM_READ,PERM_WRITE)或Auth :: currentUser() - > hasAnyPerm(Auth :: READ,Auth :: WRITE),并且在类中使用位掩码.然后,用户代码永远不会看到位掩码,您仍然可以获得位掩码的空间节省值. (4认同)