Skip to content

Instantly share code, notes, and snippets.

@ryanwinchester
Last active August 15, 2023 05:16
  • Star 14 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ryanwinchester/3a6d103be500e31dc366 to your computer and use it in GitHub Desktop.
BITWISE FLAGS for Custom PHP Objects
<?php
/**
* BITWISE FLAGS for Custom PHP Objects
*
* @link http://php.net/manual/en/language.operators.bitwise.php#108679
*
* Sometimes I need a custom PHP Object that holds several boolean TRUE or FALSE values.
* I could easily include a variable for each of them, but as always, code has a way to
* get unweildy pretty fast. A more intelligent approach always seems to be the answer,
* even if it seems to be overkill at first. I start with 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 -- so included in the class definition is the
* setFlag($flag, $value) function, which will set only the chosen bit.
*/
abstract class BitwiseFlag
{
protected $flags;
/*
* Note: these functions are protected to prevent outside code
* from falsely setting BITS. See how the extending class 'User'
* handles this.
*
*/
protected function isFlagSet($flag)
{
return (($this->flags & $flag) == $flag);
}
protected function setFlag($flag, $value)
{
if($value)
{
$this->flags |= $flag;
}
else
{
$this->flags &= ~$flag;
}
}
}
?>
The class above is abstract and cannot be instantiated, so an extension is required. Below is a simple extension called User -- which is severely truncated for clarity. Notice I am defining const variables AND methods to use them.
<?php
# User.php
require('BitwiseFlag.php');
class User extends BitwiseFlag
{
const FLAG_REGISTERED = 1; // BIT #1 of $flags has the value 1
const FLAG_ACTIVE = 2; // BIT #2 of $flags has the value 2
const FLAG_MEMBER = 4; // BIT #3 of $flags has the value 4
const FLAG_ADMIN = 8; // BIT #4 of $flags has the value 8
public function isRegistered(){
return $this->isFlagSet(self::FLAG_REGISTERED);
}
public function isActive(){
return $this->isFlagSet(self::FLAG_ACTIVE);
}
public function isMember(){
return $this->isFlagSet(self::FLAG_MEMBER);
}
public function isAdmin(){
return $this->isFlagSet(self::FLAG_ADMIN);
}
public function setRegistered($value){
$this->setFlag(self::FLAG_REGISTERED, $value);
}
public function setActive($value){
$this->setFlag(self::FLAG_ACTIVE, $value);
}
public function setMember($value){
$this->setFlag(self::FLAG_MEMBER, $value);
}
public function setAdmin($value){
$this->setFlag(self::FLAG_ADMIN, $value);
}
public function __toString(){
return 'User [' .
($this->isRegistered() ? 'REGISTERED' : '') .
($this->isActive() ? ' ACTIVE' : '') .
($this->isMember() ? ' MEMBER' : '') .
($this->isAdmin() ? ' ADMIN' : '') .
']';
}
}
?>
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.
<?php
require('User.php')
$user = new User();
$user->setRegistered(true);
$user->setActive(true);
$user->setMember(true);
$user->setAdmin(true);
echo $user; // outputs: User [REGISTERED ACTIVE MEMBER ADMIN]
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment