ModHelper

BitwiseFlag

An abstract base class which will hold a single integer variable called $flags. This simple integer can hold 32 TRUE or FALSE boolean values. Another thing to consider is to just set certain BIT values without disturbing any of the other BITS.

Note: these functions are protected to prevent outside code from falsely setting BITS.

setFlag($flag, $value) 

Will set a chosen bit

$flag The specific flag to store

The class is abstract and cannot be instantiated, so an extension is required. Below is a simple extension called User.

 1 class User extends BitwiseFlag
 2 {
 3   const FLAG_REGISTERED = 1; // BIT #1 of $flags has the value 1
 4   const FLAG_ACTIVE = 2;     // BIT #2 of $flags has the value 2
 5   const FLAG_MEMBER = 4;     // BIT #3 of $flags has the value 4
 6   const FLAG_ADMIN = 8;      // BIT #4 of $flags has the value 8
 7 
 8   public function isRegistered(){
 9     return $this->isFlagSet(self::FLAG_REGISTERED);
10   }
11 
12   public function isActive(){
13     return $this->isFlagSet(self::FLAG_ACTIVE);
14   }
15 
16   public function isMember(){
17     return $this->isFlagSet(self::FLAG_MEMBER);
18   }
19 
20   public function isAdmin(){
21     return $this->isFlagSet(self::FLAG_ADMIN);
22   }
23 
24   public function setRegistered($value){
25     $this->setFlag(self::FLAG_REGISTERED, $value);
26   }
27 
28   public function setActive($value){
29     $this->setFlag(self::FLAG_ACTIVE, $value);
30   }
31 
32   public function setMember($value){
33     $this->setFlag(self::FLAG_MEMBER, $value);
34   }
35 
36   public function setAdmin($value){
37     $this->setFlag(self::FLAG_ADMIN, $value);
38   }
39 
40   public function __toString(){
41     return 'User [' .
42       ($this->isRegistered() ? 'REGISTERED' : '') .
43       ($this->isActive() ? ' ACTIVE' : '') .
44       ($this->isMember() ? ' MEMBER' : '') .
45       ($this->isAdmin() ? ' ADMIN' : '') .
46     ']';
47   }
48 }
Code obtained fron a user contributed note on php.net

This seems like a lot of work, but we have addressed many issues, for example, using and maintaining the code is easy, and the getting and setting of flag values make sense. With the User class, you can now see how easy and intuitive bitwise flag operations become.

1 $user = new User();
2 $user->setRegistered(true);
3 $user->setActive(true);
4 $user->setMember(true);
5 $user->setAdmin(true);
6 
7 echo $user;  // outputs: User [REGISTERED ACTIVE MEMBER ADMIN]

A note about using hexadecimal numebers

Using hexadecimal numebers helps with the mental conversion between the integer value and the bit pattern it represents, which is the thing that matters for flags and masks.

Because 16 is a power of 2 (unlike 10), you get nice repeating things like this:

 1 const F0 = 0x1; // 2^0
 2 const F1 = 0x2; // 2^1
 3 const F2 = 0x4; // 2^2
 4 const F3 = 0x8; // 2^3
 5 const F4 = 0x10; // 2^4
 6 const F5 = 0x20; // 2^5
 7 const F6 = 0x40; // 2^6
 8 const F7 = 0x80; // 2^7
 9 // ...
10 const F20 = 0x1000000; // 2^20
11 const F21 = 0x2000000; // 2^21
12 const F22 = 0x4000000; // 2^22
13 const F23 = 0x8000000; // 2^23
14 const F24 = 0x10000000; // 2^24
15 // ... up to 2^31

See the pattern? You get neat groups of 1–8, and zero is appended to start a new group (leading zeros have been truncated for brevity and are optional).

In addition, hexadecimal constants indicate to the programmer that it's probably a bit mask, or a value that will be somehow involved in bitwise operations and should probably be treated specially.

Avoid using decimal notation, especially with a large amount of different flags, because it's very easy to misspell numbers like 2^20 (1048576).