fgremez / flagbag
Manipulate bitmask integers as typed PHP objects
v1.0.1
2026-03-11 20:21 UTC
Requires
- php: >=8.1
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
README
A lightweight PHP library to manipulate bitmask integers as typed objects.
No dependencies. No framework required.
Installation
composer require fgremez/flagbag
Requirements: PHP >= 8.1
Concept
Each flag is a power of 2. The stored value is the sum of active flags.
canRead = 1 → 00000001
canWrite = 2 → 00000010
canDelete = 4 → 00000100
isAdmin = 8 → 00001000
canRead + canDelete + isAdmin = 13
This allows efficient storage (a single integer column) and native SQL filtering:
SELECT * FROM user WHERE permissions & 2 = 2 -- canWrite is active SELECT * FROM user WHERE permissions & 9 = 9 -- canRead AND isAdmin are active
Usage
1. Define a FlagBag
Extend FlagBag and declare your boolean properties with #[FlagBit].
Each value must be a power of 2.
use FlagBag\FlagBag; use FlagBag\Attribute\FlagBit; class UserPermissions extends FlagBag { #[FlagBit(1)] private bool $canRead = false; #[FlagBit(2)] private bool $canWrite = false; #[FlagBit(4)] private bool $canDelete = false; #[FlagBit(8)] private bool $isAdmin = false; }
2. Hydrate from an integer
$permissions = UserPermissions::fromInt(9); // canRead (1) + isAdmin (8)
3. Read a flag
$permissions->get('canRead'); // true $permissions->get('canWrite'); // false
4. Write a flag
$permissions->set('canWrite', true); $permissions->toInt(); // 11 (1 + 2 + 8)
5. Chaining
$value = UserPermissions::fromInt(0) ->set('canRead', true) ->set('isAdmin', true) ->toInt(); // 9
6. Integrate with any class
The column stays a plain integer — no custom ORM type needed.
class User { private int $permissions = 0; public function getPermissions(): UserPermissions { return UserPermissions::fromInt($this->permissions); } public function setPermissions(UserPermissions $bag): void { $this->permissions = $bag->toInt(); } }
$user->setPermissions( $user->getPermissions()->set('canWrite', true) );
Exceptions
| Exception | Thrown when |
|---|---|
UnknownFlagException |
get()/set() called with a flag name that does not exist |
InvalidFlagBitValueException |
A #[FlagBit] value is not a power of 2 |
FlagBitCollisionException |
Two properties share the same #[FlagBit] value |
Integer limits
| Storage | Size | Max flags | Max value |
|---|---|---|---|
| TINYINT | 8 bits | 7 | 127 |
| SMALLINT | 16 bits | 15 | 32 767 |
| INT | 32 bits | 31 | 2 147 483 647 |
| BIGINT | 64 bits | 62 | ~4.6×10¹⁸ |
License
MIT — see LICENSE