Pregunta

Estoy trabajando en un sistema fácil de papel / permiso en PHP para un guión.

A continuación se muestra un código utilizando un método de máscara de bits para los permisos que he encontrado en phpbuilder.com.

Por debajo de esa parte es una versión mucho más simple w3hich podía hacer básicamente lo mismo sin la parte de bits.

Muchas personas han recomendado el uso de los operadores de bits y tal para ajustes y otras cosas en PHP, nunca he entendido por qué sin embargo. En el código de abajo está allí ningún beneficio utilizando el primer código en lugar de la segunda?

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

versión no poco

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

?>
¿Fue útil?

Solución

¿Por qué no hacer esto ...

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

También puede crear un montón de combinaciones arbitrarias de permisos, si lo utilice brocas ...

$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

Otros consejos

La primera permite que la gente tenga un montón de permisos - leer / añadir / actualizar por ejemplo. El segundo ejemplo, el usuario acaba de PERMISSION_UPDATE.

bit a bit prueba funciona mediante pruebas de bits para los valores de verdad.

Por ejemplo, el 10010 secuencia binaria sería identificar a un usuario con PERMISSION_DELETE y PERMISSION_READ (el bit de identificación de PERMISSION_READ es la columna para 2, el bit de identificación de PERMISSION_DELETE es la columna para 16), 10010 en binario es 18 en decimal (16 + 2 = 18). Su segundo ejemplo de código no permite que hagas ese tipo de pruebas. Usted podría hacer mayor que los controles de estilo, pero que asume todos con PERMISSION_DELETE también debe tener PERMISSION_UPDATE, que puede no ser una suposición válida.

Tal vez sea sólo porque yo no uso máscaras de bits muy a menudo, pero me parece que en un lenguaje como PHP, donde la productividad del desarrollador y la legibilidad del código son más importantes que la velocidad o el uso de memoria (dentro de unos límites, obviamente), no hay razón verdadera utilizar bitmasking.

¿Por qué no en lugar de crear una clase que rastrea cosas como permisos, y se registra en los usuarios, y así sucesivamente? Digamos que es de autenticación. Entonces, si usted quiere comprobar que un usuario tiene un permiso, se puede crear un HasPermission método. por ejemplo.,

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

A continuación, si desea comprobar si tienen alguna combinación de permisos:

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

o si desea comprobar si tienen cualquiera de un cierto grupo de permisos:

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

Por supuesto, puede que no sea una mala idea para definir constantes, como PERMISSION_READ, que sólo se puede definir a ser la cadena 'leer', y así sucesivamente.

Me parece que este enfoque más fácil de leer que máscaras de bits debido a que los nombres de los métodos que dicen exactamente qué es lo que está buscando.

Editar : releer la pregunta, parece que los permisos del usuario están regresando a su base de datos en un campo de bits. Si ese es el caso, usted va a tener que utilizar operadores bit a bit. Un usuario que es el permiso en la base de datos es 5 tiene PERMISSION_READ y PERMISSION_DENIED porque (PERMISSION_READ & 5) != 0 y (PERMISSION_DENIED & 5) != 0. No tendría PERMISSION_ADD, porque (PERMISSION_ADD & 5) == 0

¿Tiene sentido? Toda la materia compleja en su ejemplo a nivel de bits parece innecesaria.


Si no se entiende completamente las operaciones bit a bit, entonces no los utilizan. Es sólo dará lugar a un montón de dolores de cabeza. Si se siente cómodo con ellos, luego usarlos donde se siente que son apropiados. Usted (o quien escribió el código de bit a bit) no parece comprender plenamente operaciones bit a bit. Hay varios problemas con él, al igual que el hecho de que se utiliza la función pow(), que anularía cualquier tipo de beneficio en el rendimiento. (En lugar de pow(2, $n), se debe utilizar el 1 << $n bit a bit, por ejemplo.)

Dicho esto, no parece que hacer las mismas cosas que las dos piezas de código.

Trate de usar lo que está en el bit.class.php http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php

Comprobación contra un bit específico:

<?php

define('PERMISSION_DENIED', 1);
define('PERMISSION_READ', 2);
define('PERMISSION_ADD',  3);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 5);


if(bit::query($permission,PERMISSION_DENIED)){
echo 'Your permission is denied';
exit();
}else{
// so on
}

?>

Y para encender y apagar:

<?php

$permissions = 8;
bit::toggle(&$permissions,PERMISSION_DENIED);

var_dump($permissions); // outputs int(9)

?>

problema de esto es que si PERMISSION_READ es una máscara en sí

if($ARR_permission & PERMISSION_READ) {
    echo 'Access granted.';
}else {
    echo 'Access denied.';

entonces para 0101 - $ rightWeHave 0011 - $ rightWeRequire

que se concede el acceso, que probablemente no queremos lo que debe ser

if (($rightWeHave & $rightWeRequire) == $rightWeRequire) {
echo 'access granted';
}

por lo que ahora para

0101 0011

resultado es

0001 por lo que no se concede acceso, ya que no es igual a 0011

pero por

1101 0101

es aceptable, pues el resultado es 0101

archivo de comandos que la máscara se ha puesto en decimal. Tal vez alguien que necesitará:

<?php

$max = 1073741824;
$series = array(0);
$x = 1;
$input = $argv[1]; # from command line eg.'12345': php script.php 12345
$sum = 0;

# generates all bitmasks (with $max)
while ($x <= $max) {
    $series[] = $x;
    $x = $x * 2;
}

# show what bitmask has been set in '$argv[1]'
foreach ($series as $value) {
    if ($value & $input) {
        $sum += $value;
        echo "$value - SET,\n";
    } else {
        echo "$value\n";
    }
}

# sum of set masks
echo "\nSum of set masks: $sum\n\n";

Salida (php maskChecker.php 123):

0
1 - SET,
2 - SET,
4
8 - SET,
16 - SET,
32 - SET,
64 - SET,
128
256
512
1024
2048
4096
8192
(...)

Sum of set mask: 123

Creo que el primer ejemplo le da más control de exactamente los permisos que un usuario tiene. En el segundo sólo hay un 'nivel' usuario; presumiblemente niveles más altos heredar todos los permisos concedidos a un usuario menor 'nivel', por lo que no tienen un control tan bien.

Además, si he entendido bien, la línea

if($user_permission_level === 4)

significa que sólo los usuarios con exactamente nivel de permiso 4 tienen acceso a la acción - seguramente querrían para comprobar que los usuarios tengan al menos de ese nivel?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top