很长一段时间以来,我一直试图找出在 PHP 中使用位掩码或位域的最佳方法,用于我的应用程序的不同区域,以获得不同的用户设置和权限。到目前为止,我所走的最远的是 svens 在 Stack Overflow 帖子 Bitmask in PHP for settings 中贡献的一个类?. 我在下面稍微修改了它,将其更改为使用类常量而不是 DEFINE,并确保 get 方法仅传递一个 int。我还有一些示例代码来测试下面的类的功能。
我正在寻找任何建议/代码来进一步改进这个类,以便它可以在我的应用程序中用于设置,并在某些情况下用于用户权限。
mcrumley 在下面的评论中回答了
另外,我有一个关于常量编号的问题。在此类型的其他类和代码示例中,它将以 2 的幂列出的内容。但是,据我所知,即使我将常量编号为 1、2、3、4、5、6,它的工作方式似乎也是一样的而不是 1、2、4、8、16 等。那么有人可以澄清我是否应该改变我的常数吗?
一些想法......我真的很想找到一种方法来扩展这个类,这样它就可以很容易地与其他类一起使用。假设我有一个User
班级和一个Messages
班级。User
和_Messages
类将扩展此类并能够将位掩码用于其设置/权限(以及稍后的其他类)。因此,也许应该更改当前的类常量,以便可以传入它们或其他一些选项?我真的宁愿不必在站点/脚本的其他部分定义 (define('PERM_READ', 1);) 并且希望保持它的某种封装,但也很灵活;我对想法持开放态度。我希望它是坚如磐石和灵活的,就像我说的与多个其他类一起用于设置或权限。可能应该使用某种数组?@Svens 来自我上面链接的上一个问题,发表了一条评论,“实现一些自动的 getter/setter 或 ArrayAccess 以获得额外的效果。- svens”你对类似的事情也有什么看法?
如果可能,请包含示例源代码。
<?php
class BitField {
const PERM_READ = 0;
const PERM_WRITE = 1;
const PERM_ADMIN = 2;
const PERM_ADMIN2 = 3;
const PERM_ADMIN3 = 4;
private $value;
public function __construct($value=0) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
public function get($n) {
if (is_int($n)) {
return ($this->value & (1 << $n)) != 0;
}else{
return 0;
}
}
public function set($n, $new=true) {
$this->value = ($this->value & ~(1 << $n)) | ($new << $n);
}
public function clear($n) {
$this->set($n, false);
}
}
?>
示例用法...
<?php
$user_permissions = 0; //This value will come from MySQL or Sessions
$bf = new BitField($user_permissions);
// Turn these permission to on/true
$bf->set($bf::PERM_READ);
$bf->set($bf::PERM_WRITE);
$bf->set($bf::PERM_ADMIN);
$bf->set($bf::PERM_ADMIN2);
$bf->set($bf::PERM_ADMIN3);
// Turn permission PERM_ADMIN2 to off/false
$bf->clear($bf::PERM_ADMIN2); // sets $bf::PERM_ADMIN2 bit to false
// Get the total bit value
$user_permissions = $bf->getValue();
echo '<br> Bitmask value = ' .$user_permissions. '<br>Test values on/off based off the bitmask value<br>' ;
// Check if permission PERM_READ is on/true
if ($bf->get($bf::PERM_READ)) {
// can read
echo 'can read is ON<br>';
}
if ($bf->get($bf::PERM_WRITE)) {
// can write
echo 'can write is ON<br>';
}
if ($bf->get($bf::PERM_ADMIN)) {
// is admin
echo 'admin is ON<br>';
}
if ($bf->get($bf::PERM_ADMIN2)) {
// is admin 2
echo 'admin 2 is ON<br>';
}
if ($bf->get($bf::PERM_ADMIN3)) {
// is admin 3
echo 'admin 3 is ON<br>';
}
?>