Bit Flags
Anzeige Hier werben
Mit Hilfe von bit flags kann man mehrere Zustände in einer einzigen Zahl unterbringen. Dies ist z.B. bei Rückgabewerten von Funktionen nützlich. In diesem Tutorial zeige ich die Verwendung von Bit-Flags anhand einer einfachen Formular-Überprüfung mit PHP.
Zunächst definieren wir einige Konstanten welche die einzelnen Flags repräsentieren. Diese verbessern später die Lesbarkeit des Codes. Sind aber nicht zwingend erforderlich.
Um zu verstehen was Bit-Flags eigentlich sind, schreiben wir das ganze in binärer Form.
Flag setzen
Nun initialisiert man zunächst die Fehlercode-Variable ($failure_code) mit 0. Möchte man ein bestimmtes Flag setzen bedient man sich einer sogenannten Bitmaske. Die Bitmaske entspricht dem zu setzenden Bit. Bitmaske und Wert verknüpft man mit einem bitweisen OR (|). Die beiden Werte werden dadurch bit für bit mit einem OR verknüpft. Im folgenden Beispiel wird das _NO_PASSWORD-bit gesetzt. Die entsprechende Bitmaske wäre also 000010 (Dezimal: 2)
1 2 3 4 5 6 7 8 9 10 11 | 000000 Wert
OR 000010 Bitmaske
_________
000010
Einen weiteres Flag setzen:
000010 Wert
OR 010000 Bitmaske
_________
010010
|
In PHP sieht dies wie folgt aus:
1 2 3 | $failure_code = 0;
$failure_code |= _NO_PASSWORD;
|
Flag auslesen
Hier kommt wieder die Bitmaske ins Spiel. Diese verknüpft man diesmal aber mit einem bitweisen AND (&) mit dem Wert. Die beiden binären zahlen werden dadurch bit für bit mit einem AND verknüpft. Ergebnis dieser Operation ist entweder 1 (true) oder 0 (false). Im folgenden Beispiel wird überprüft ob das _NO_EMAIL-Bit gesetzt ist. Die entsprechende Bitmaske wäre also 000100 (Dezimal: 4).
1 2 3 4 5 6 7 8 9 10 11 12 13 | Fall 1: Bit/Flag ist gesetzt.
000100 Wert
AND 000100 Bitmaske
__________
000100 True
Fall 2: Bit/Flag ist nicht gesetzt.
000000 Wert
AND 000100 Bitmaske
__________
000000 False
|
In PHP sieht das ganze wie folgt aus:
1
2
3
4
5
6 | $failure_code = 0;
if($failure_code &_NO_EMAIL)
echo 'Flag/Bit ist gesetzt.';
else
echo 'Flag/Bit ist nicht gesetzt.';
|
Beispiel
Nun ein praktisches Beispiel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | <?php
define('_NO_USERNAME', 1);
define('_NO_PASSWORD', 2);
define('_NO_EMAIL', 4);
define('_INVALID_USERNAME', 8);
define('_INVALID_PASSWORD', 16);
define('_INVALID_EMAIL', 32);
function validate($username,$password,$email)
{
$failure_code = 0;
if($username == '')
$failure_code |= _NO_USERNAME;
if($password == '')
$failure_code |= _NO_PASSWORD;
if($email == '')
$failure_code |= _NO_EMAIL;
if(!preg_match('~^[a-zA-z0-9].*~',$username))
$failure_code |= _INVALID_USERNAME;
$strlen = strlen($password);
if($strlen<20 && $strlen>4)
$failure_code |= _INVALID_PASSWORD;
if(!preg_match('~^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|coop|info|museum|name))$~',$email))
$failure_code |= _INVALID_EMAIL;
return $failure_code;
}
if($_GET['action']=='validate')
{
$failure_code = validate($_POST['username'],$_POST['password'],$_POST['email']);
if($failure_code==0)
echo 'Alles korrekt.';
else
{
if($failure_code &_NO_USERNAME)
echo 'Username fehlt.';
if($failure_code &_NO_EMAIL)
echo 'E-Mail fehlt.';
if($failure_code &_NO_PASSWORD)
echo 'Passwort fehlt.';
if($failure_code &_INVALID_USERNAME)
echo 'Username ungültig.';
if($failure_code &_INVALID_EMAIL)
echo 'E-Mail ungültig.';
if($failure_code &_INVALID_PASSWORD)
echo 'Passwort ungültig.';
}
?>
<form action="?action=validate" method="post">
Username<br/>
<input type="text" name="username" /><br/>
Passwort<br/>
<input type="password" name="password" /><br/>
E-Mail<br/>
<input type="text" name="email" /><br/>
</form>
|


Hochkommata/Anführungsstriche
Also ich ersten Codebeispiel (die 6 defines) würde man schon 6 Notices bekommen bzgl. "undefined constant". Die Funktion define() verlangt als ersten Parameter einen String. Somit muss man den Namen der Konstante auch in Hochkommata (') oder Anführungsstrichen (") setzen.
Re: Hochkommata/Anführungsstriche
hmm ja sowas passiert wenn man nicht testet. Danke für den Hinweis...
Wie $failure_code erstellt wird
Du verwendest im Code um
$failure_codezusammenzustellen immer sowas wie:$failure_code += _NO_USERNAME;. Sauberer wäre aber$failure_code |= _NO_USERNAME;, da hier keine "Überläufe" stattfinden können. Vielleicht kannst du das noch ändern. Im Beispiel macht es zwar keinen Unterschied, wär aber sauberer und sollte weniger fehleranfällig sein. ;-)Re: Wie $failure_code erstellt wird
danke für den Hinweis. Hab's mal verbessert...