Why should I use bitwise/bitmask in PHP?

I am working on a user-role / permission system in PHP for a script.

Below is a code using a bitmask method for permissions that I found on phpbuilder.com.

Below that part is a much simpler version w3hich could do basicly the same thing without the bit part.

Many people have recommended using bit operators and such for settings and other things in PHP, I have never understood why though. In the code below is there ANY benefit from using the first code instead of the second?

<?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.';
}
?>

non-bit version

<?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.';
}

?>

Why not just do this...

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.';
}

You can also create lots of arbitrary combinations of permissions if you use bits...

$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

The first allows people to have lots of permissions - read/add/update for example. The second example, the user has just PERMISSION_UPDATE .

Bitwise testing works by testing bits for truth values.

For example, the binary sequence 10010 would identify a user with PERMISSION_DELETE and PERMISSION_READ (the bit identifying PERMISSION_READ is the column for 2, the bit identifying PERMISSION_DELETE is the column for 16), 10010 in binary is 18 in decimal (16 + 2 = 18). Your second code sample doesn't allow you to do that sort of testing. You could do greater-than style checks, but that assumes everyone with PERMISSION_DELETE should also have PERMISSION_UPDATE , which may not be a valid assumption.


Maybe it's just because I don't use bitmasks very often, but I find that in a language like PHP where developer productivity and code readability are more important than speed or memory usage (within limits, obviously), there's no real reason to use bitmasking.

Why not instead create a class that tracks things like permissions, and logged in users, and so on? Let's call it Auth. Then, if you want to check that a user has a permission, you can create a method HasPermission. eg,

if(Auth::logged_in() && Auth::currentUser()->hasPermission('read'))
    //user can read

then if you want to check whether they have some combination of permissions:

if(Auth::logged_in() && Auth::currentUser()->hasAllPermissions('read', 'write'))
    //user can read, and write

or if you want to check whether they have any of a certain group of permissions:

if(Auth::logged_in() && Auth::currentUser()->hasAnyPermissions('read', 'write'))
    //user can read, or write

Of course, it may not be a bad idea to define constants, such as PERMISSION_READ, which you can just define to be the string 'read', and so on.

I find this approach easier to read than bitmasks because the method names tell you exactly what it is you're looking for.

链接地址: http://www.djcxy.com/p/57600.html

上一篇: 位运算符的实际应用

下一篇: 为什么我应该在PHP中使用bitwise / bitmask?