改进这个PHP位域类的设置/权限?
我一直试图找出在PHP中使用位掩码或位域的最佳方法,现在我的应用程序的不同区域用于不同的用户设置和权限。我到目前为止最远的是来自Stack Overflow中由svens贡献的类
在PHP中发布用于设置的位掩码?我稍微对它进行了修改,将其更改为使用类常量而不是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发表评论“实现一些自动获取者/设置者或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>';
}
?>
没有找到相关结果
已邀请:
5 个回复
碧肮械淌设
然后使用简单地变成:
要设置隐私设置,您只需实例化一个新的UserPrivacySettings_BitField对象并使用它。 这样,您可以通过定义一组代表您的选项的常量,创建与应用程序所需的任意数量的不同BitField对象集。 我希望这对你有一些用处,但如果没有,也许它会对读这篇文章的其他人有所帮助。
替秀宝
让我们在PHP交互式提示符下检查这些权限的位值:
现在让我们创建一个具有READ访问权限和WRITE访问权限的用户。
或者可以读取,写入,删除但不能编辑的用户:
我们可以使用bitwise-AND检查权限并确保结果不为零:
(值得注意的是,
是
,这是零。我创建的“无”权限实际上并不适用于此,并且可以立即被遗忘。) 你的班级正在做一些略有不同的事情,但最终结果是相同的。它使用位移来将“on”位向左移动X次,其中X是权限的数量。实际上,这会使权限值增加2。示范:
虽然这些方法实际上是相同的,但我认为简单的ANDing和ORing比XORing和位移更容易阅读。 我正在寻找任何建议/代码来进一步改进这个类,所以它可以在我的应用程序中用于设置和某些情况下的用户权限。 我有一个建议,一个警告。 我的建议是使类抽象而不是在其中定义任何权限。相反,构建从其继承并定义自己的权限的类。您不希望考虑在不相关的位字段之间共享相同的权限名称,并且为它们添加类名称是非常明智的。无论如何,我希望你会这样做。 我的警告很简单但很可怕:PHP无法可靠地表示大于31位的整数。实际上,当它在64位系统上编译时,它只能代表63位整数。这意味着,如果您要将应用程序分发给公众,如果您希望使用内置数学函数,则限制为不超过31个权限。 GMP扩展包括可以在任意长度整数上运行的按位运算。 另一种选择可能是在大整数上使用这个答案的代码,这可能允许你将一个巨大的整数表示为一个字符串,尽管对它进行按位操作可能会很有趣。 (您可以将其下转换为base-2,然后在预期位置对字符串“1”或“0”进行子检查,但这将是一个巨大的性能阻力。)
豪抱怒掳
如您所见,我使用了1,2,4,8等(2的幂)来简化计算。如果您将一个权限映射到一个位,您有:
然后你可以使用逻辑运算,例如你最初有这个:
如果要添加写入权限,则只需使用按位OR运算符:
要删除一位,你必须使用$ value&amp; 〜$ bit,例如删除写位:
最后,如果要测试是否启用了一个位,则必须对要测试的PERM_XXX进行AND $值操作:
如果结果不为零,则表示您拥有该权限,否则您将获得该权限。
破弯
&LT;编辑&gt; 没有十六进制值的同一个类的可读性较差,特别是如果添加更多标志:
&LT; /编辑&gt; 我将进一步定义set()的参数必须是单位整数,而不是标志号。恶魔的set()实现是我的意思:
揽芳僵迷仇