I kept running into the same problem across different Laravel projects: storing and querying multiple boolean flags efficiently. User permissions, feature toggles, notification settings - they all followed the same pattern but required different solutions.
The obvious approach is separate boolean columns, but that gets unwieldy fast. Ten permission flags means ten database columns and increasingly complex queries when you need to find users with specific combinations.
Bitwise flags solve this by storing multiple boolean values as powers of 2 in a single integer column. It's an old technique that works well, but Laravel needed a cleaner way to work with them.
Configuration Options
There are a few ways to define bitwise flags depending on your needs:
protected function casts(): array
{
return [
// Auto-generate flags from names
'permissions' => AsBitwise::auto(['read', 'write', 'delete', 'admin']),
// Define flags with explicit values
'features' => AsBitwise::flags(['notifications' => 1, 'dark_mode' => 2]),
// Laravel-native shorthand syntax
'roles' => 'bitwise:user,moderator,admin',
];
}
Query Macros
Instead of requiring traits on every model, the package registers query macros directly on Laravel's builder. This means bitwise queries work on any model without extra setup:
User::whereBitwise('permissions', 'admin')->get();
User::whereHasAnyBitwise('permissions', ['write', 'delete'])->get();
User::whereDoesntHaveBitwise('permissions', 'admin')->get();
These generate the expected SQL with bitwise operations:
-- For whereBitwise('permissions', 'admin')
SELECT * FROM users WHERE (permissions & 8) = 8
-- For whereHasAnyBitwise('permissions', ['read', 'write'])
SELECT * FROM users WHERE (permissions & 3) > 0
Working with Flags
The BitwiseCollection
class handles flag manipulation. Methods return new instances rather than modifying the original:
$user = User::find(1);
if ($user->permissions->has('admin')) {
// User has admin access
}
$user->permissions = $user->permissions->add('write', 'delete');
$user->save();
$user->permissions = $user->permissions->toggle('beta_features');
Why This Approach
Bitwise flags aren't new, but most implementations either require traits on every model or lack proper Laravel integration. The macro approach means any model can use bitwise queries without modification.
Storage is efficient - 20 flags fit in a single integer column. Database queries are fast since bitwise operations happen at the SQL level. And the API feels natural in Laravel applications.