Warum sollte ich bitweise / Bitmaske in PHP?
-
21-09-2019 - |
Frage
Ich arbeite an einem Benutzer-Rolle / Berechtigungssystem in PHP für ein Skript.
Im Folgenden ist ein Code, der eine Bitmaske Methode für Berechtigungen verwenden, dass ich auf phpbuilder.com gefunden.
Darunter Teil eine viel einfachere Version ist w3hich ohne den Bit-Teil basicly das gleiche tun könnte.
Viele Leute haben empfohlen, mit Bit-Operatoren und solche für Einstellungen und andere Dinge in PHP, habe ich nie verstanden, warum though. Im folgenden Code ist es ANY Nutzen aus dem ersten Code anstelle den zweiten mit?
<?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.';
}
?>
Nicht-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.';
}
?>
Lösung
Warum nicht einfach das tun ...
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.';
}
Sie können auch viele beliebige Kombinationen von Berechtigungen erstellen, wenn Sie Bits verwenden ...
$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
Andere Tipps
Die erste ermöglicht es den Menschen viele Berechtigungen zu haben - Lese- / Add / Update zum Beispiel. Das zweite Beispiel, der Benutzer hat nur PERMISSION_UPDATE
.
Bitwise Werke Prüfung von Bits für Wahrheitswerte testen.
Zum Beispiel kann die Binärfolge 10010
einen Benutzer mit PERMISSION_DELETE
und PERMISSION_READ
identifizieren würde (das Bit PERMISSION_READ
Identifizierung ist die Säule für 2, das Bit PERMISSION_DELETE
Identifizierung ist die Spalte 16), 10010
in binär 18 in dezimalem (16 + 2 = 18). Ihr zweites Codebeispiel erlaubt Ihnen nicht, diese Art von Tests zu tun. Sie tun können, Größer-als-Stil überprüft, aber das setzt voraus, jeder mit PERMISSION_DELETE
auch PERMISSION_UPDATE
haben sollte, die keine gültige Annahme sein kann.
Vielleicht ist es nur, weil ich Bitmasken nicht sehr oft, aber ich, dass wie PHP in einer Sprache finden, wo die Produktivität der Entwickler und die Lesbarkeit des Codes ist wichtiger als Geschwindigkeit oder Speicherauslastung (in Grenzen, natürlich), gibt es keinen wirklichen Grund zur Verwendung bitmasking.
Warum nicht stattdessen eine Klasse, die Spuren Dinge wie Berechtigungen und eingeloggte Benutzer, und so weiter? Nennen wir es Auth. Dann, wenn Sie überprüfen möchten, dass ein Benutzer eine Berechtigung hat, können Sie eine Methode HasPermission erstellen. z. B.
if(Auth::logged_in() && Auth::currentUser()->hasPermission('read'))
//user can read
dann, wenn Sie wollen prüfen, ob sie eine Kombination von Berechtigungen verfügen:
if(Auth::logged_in() && Auth::currentUser()->hasAllPermissions('read', 'write'))
//user can read, and write
oder wenn Sie wollen prüfen, ob sie irgendeine eine bestimmte Gruppe von Berechtigungen verfügen:
if(Auth::logged_in() && Auth::currentUser()->hasAnyPermissions('read', 'write'))
//user can read, or write
Natürlich kann es keine schlechte Idee sein Konstanten zu definieren, wie PERMISSION_READ, die Sie gerade definieren können die Zeichenfolge ‚lesen‘ zu sein, und so weiter.
ich diesen Ansatz einfacher finden als Bitmasken zu lesen, weil die Methodennamen Ihnen genau sagen, was es ist, die Sie suchen.
Bearbeiten : die Frage rereading, es sieht aus wie die Berechtigungen des Benutzers zurück aus Ihrer Datenbank in einem Bitfeld kommen. Wenn das der Fall ist, sind Sie gehen zu müssen Bitoperatoren verwenden. Ein Benutzer, der die Berechtigung in der Datenbank ist, ist 5
hat PERMISSION_READ
und PERMISSION_DENIED
weil (PERMISSION_READ & 5) != 0
und (PERMISSION_DENIED & 5) != 0
. Er würde nicht PERMISSION_ADD
haben, weil (PERMISSION_ADD & 5) == 0
Ist das sinnvoll? Die ganze Komplex Material in Ihrem bitweise Beispiel sieht nicht erforderlich.
Wenn Sie nicht vollständig bitweise Operationen verstehen, dann sie nicht verwenden. Es wird nur eine Menge Kopfschmerzen führen. Wenn Sie mit ihnen vertraut sind, sie dann verwenden, wenn Sie das Gefühl, sie angemessen sind. Sie (oder wer auch immer das bitweise Code geschrieben hat) scheint nicht vollständig bitweise Operationen zu erfassen. Es gibt mehrere Probleme mit sich, wie die Tatsache, dass die pow()
Funktion verwendet wird, die jede Art von Leistungsvorteil zunichte machen würde. (Statt pow(2, $n)
, sollten Sie die bitweise 1 << $n
verwenden, zum Beispiel.)
sagte, dass die beiden Teile des Codes scheinen nicht die gleichen Dinge zu tun.
Versuchen Sie es mit, was in der bit.class.php ist unter http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php
Überprüfen gegen ein bestimmtes Bit:
<?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
}
?>
Und zum Ein- und Ausschalten:
<?php
$permissions = 8;
bit::toggle(&$permissions,PERMISSION_DENIED);
var_dump($permissions); // outputs int(9)
?>
Problem dafür ist, wenn PERMISSION_READ eine Maske selbst
if($ARR_permission & PERMISSION_READ) {
echo 'Access granted.';
}else {
echo 'Access denied.';
dann für 0101 - $ rightWeHave 0011 - $ rightWeRequire
es Zugriff gewährt wird, die wir wahrscheinlich nicht wollen, so sollte es sein
if (($rightWeHave & $rightWeRequire) == $rightWeRequire) {
echo 'access granted';
}
so jetzt
0101 0011
Ergebnis
0001 so Zugang nicht gewährt, weil es nicht zu 0011 gleich
aber für
1101 0101
Es ist in Ordnung, da das Ergebnis 0101 ist
Script überprüft, welche Maske gesetzt worden ist in dezimal. Vielleicht hat jemand wird es brauchen:
<?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";
Output (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
Ich denke, das erste Beispiel gibt Ihnen mehr Kontrolle über genau, welche Berechtigungen ein Benutzer hat. In der zweiten haben Sie nur einen Benutzer-Ebene '; vermutlich höhere Ebene erben alle erteilten Berechtigungen auf einen niedrigeren ‚Ebene‘ Benutzer, so dass Sie nicht so feine Kontrolle haben.
Auch wenn ich das richtig verstanden habe, die Zeile
if($user_permission_level === 4)
bedeutet, dass nur Benutzer mit genau Berechtigungsstufe 4 haben Zugriff auf die Aktion - sicher würden Sie überprüfen möchten, dass Benutzer mindestens , dieses Niveau?