PHP 中的位掩码设置?
位和位掩码是我一段时间以来一直难以理解的东西,但我想学习如何在 PHP 中使用它们进行设置和类似的操作。
我终于找到了一个声称可以做到这一点的课程,据我所知,它似乎有效,但我不确定这是否是最好的方法。我将在下面发布带有示例代码的类文件,以显示它的工作顺序。
如果您有经验,请告诉我是否可以改进,无论是性能还是其他方面。我真的很想学习这一点,并且我一直在阅读它,但到目前为止对我来说很难掌握。
类...
<?php
class bitmask
{
/**
* This array is used to represent the users permission in usable format.
*
* You can change remove or add valuesto suit your needs.
* Just ensure that each element defaults to false. Once you have started storing
* users permsisions a change to the order of this array will cause the
* permissions to be incorectly interpreted.
*
* @type Associtive array
*/
public $permissions = array(
"read" => false,
"write" => false,
"delete" => false,
"change_permissions" => false,
"admin" => false
);
/**
* This function will use an integer bitmask (as created by toBitmask())
* to populate the class vaiable
* $this->permissions with the users permissions as boolean values.
* @param int $bitmask an integer representation of the users permisions.
* This integer is created by toBitmask();
*
* @return an associatve array with the users permissions.
*/
public function getPermissions($bitMask = 0)
{
$i = 0;
foreach ($this->permissions as $key => $value)
{
$this->permissions[$key] = (($bitMask & pow(2, $i)) != 0) ? true : false;
// Uncomment the next line if you would like to see what is happening.
//echo $key . " i= ".strval($i)." power=" . strval(pow(2,$i)). "bitwise & = " . strval($bitMask & pow(2,$i))."<br>";
$i++;
}
return $this->permissions;
}
/**
* This function will create and return and integer bitmask based on the permission values set in
* the class variable $permissions. To use you would want to set the fields in $permissions to true for the permissions you want to grant.
* Then call toBitmask() and store the integer value. Later you can pass that integer into getPermissions() to convert it back to an assoicative
* array.
*
* @return int an integer bitmask represeting the users permission set.
*/
function toBitmask()
{
$bitmask = 0;
$i = 0;
foreach ($this->permissions as $key => $value)
{
if ($value)
{
$bitmask += pow(2, $i);
}
$i++;
}
return $bitmask;
}
}
?>
如何将权限设置/保存为位掩码值?
<?php
/**
* Example usage
* initiate new bitmask object
*/
$perms = new bitmask();
/**
* How to set permissions for a user
*/
$perms->permissions["read"] = true;
$perms->permissions["write"] = true;
$perms->permissions["delete"] = true;
$perms->permissions["change_permissions"] = true;
$perms->permissions["admin"] = false;
// Converts to bitmask value to store in database or wherever
$bitmask = $perms->toBitmask(); //in this example it is 15
$sql = "insert into user_permissions (userid,permission) values(1,$bitmask)";
echo $sql; //you would then execute code to insert your sql.
?>
获取位掩码值并根据位值为每个数组项返回 true/false 的示例......
<?php
/**
* Example usage to get the bitmask value from database or session/cache.... then put it to use.
* $permarr returns an array with true/false for each array value based on the bit value
*/
$permarr = $perms->getPermissions($bitmask);
if ($permarr["read"])
{
echo 'user can read: <font color="green">TRUE</font>';
}
else {
echo 'user can read: <font color="red">FALSE</font>';
}
//user can WRITE permission
if ($permarr["write"])
{
echo '<br>user can write: <font color="green">TRUE</font>';
}
else {
echo '<br>user can write: <font color="red">FALSE</font>';
}
?>
Bits and bitmask are something I have been struggling to understand for a while, but I would like to learn how to use them for settings and things like that in PHP.
I have finally found a class that claims to do exactly that, and as I can tell, it seems to work, but I am not sure if it is the best way of doing this. I will post the class file with example code below to show it in working order.
Please if you have experience, tell me if it can be improved, for performance or anything else. I really want to learn this, and I have been reading up on it, but it is a difficult one for me to grasp so far.
The class...
<?php
class bitmask
{
/**
* This array is used to represent the users permission in usable format.
*
* You can change remove or add valuesto suit your needs.
* Just ensure that each element defaults to false. Once you have started storing
* users permsisions a change to the order of this array will cause the
* permissions to be incorectly interpreted.
*
* @type Associtive array
*/
public $permissions = array(
"read" => false,
"write" => false,
"delete" => false,
"change_permissions" => false,
"admin" => false
);
/**
* This function will use an integer bitmask (as created by toBitmask())
* to populate the class vaiable
* $this->permissions with the users permissions as boolean values.
* @param int $bitmask an integer representation of the users permisions.
* This integer is created by toBitmask();
*
* @return an associatve array with the users permissions.
*/
public function getPermissions($bitMask = 0)
{
$i = 0;
foreach ($this->permissions as $key => $value)
{
$this->permissions[$key] = (($bitMask & pow(2, $i)) != 0) ? true : false;
// Uncomment the next line if you would like to see what is happening.
//echo $key . " i= ".strval($i)." power=" . strval(pow(2,$i)). "bitwise & = " . strval($bitMask & pow(2,$i))."<br>";
$i++;
}
return $this->permissions;
}
/**
* This function will create and return and integer bitmask based on the permission values set in
* the class variable $permissions. To use you would want to set the fields in $permissions to true for the permissions you want to grant.
* Then call toBitmask() and store the integer value. Later you can pass that integer into getPermissions() to convert it back to an assoicative
* array.
*
* @return int an integer bitmask represeting the users permission set.
*/
function toBitmask()
{
$bitmask = 0;
$i = 0;
foreach ($this->permissions as $key => $value)
{
if ($value)
{
$bitmask += pow(2, $i);
}
$i++;
}
return $bitmask;
}
}
?>
How do I set/save the permissions as a bitmask value?
<?php
/**
* Example usage
* initiate new bitmask object
*/
$perms = new bitmask();
/**
* How to set permissions for a user
*/
$perms->permissions["read"] = true;
$perms->permissions["write"] = true;
$perms->permissions["delete"] = true;
$perms->permissions["change_permissions"] = true;
$perms->permissions["admin"] = false;
// Converts to bitmask value to store in database or wherever
$bitmask = $perms->toBitmask(); //in this example it is 15
$sql = "insert into user_permissions (userid,permission) values(1,$bitmask)";
echo $sql; //you would then execute code to insert your sql.
?>
Example of taking the bitmask value and returning a true/false for each array item based on the bit value....
<?php
/**
* Example usage to get the bitmask value from database or session/cache.... then put it to use.
* $permarr returns an array with true/false for each array value based on the bit value
*/
$permarr = $perms->getPermissions($bitmask);
if ($permarr["read"])
{
echo 'user can read: <font color="green">TRUE</font>';
}
else {
echo 'user can read: <font color="red">FALSE</font>';
}
//user can WRITE permission
if ($permarr["write"])
{
echo '<br>user can write: <font color="green">TRUE</font>';
}
else {
echo '<br>user can write: <font color="red">FALSE</font>';
}
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
位字段是处理标志或任何布尔值集合的非常方便且高效的工具。
要理解它们,您首先需要了解二进制数的工作原理。之后,您应该查看 按位运算符 上的手动条目,并确保你知道按位“与”、“或”和左/右移位是如何工作的。
位字段只不过是一个整数值。假设我们的位字段的大小是固定的并且只有一个字节。计算机使用二进制数字,因此如果我们的数字值为
29
,您实际上会在内存中找到0001 1101
。使用按位与 (
&
) 和按位或 (|
),您可以单独读出并设置数字的每一位。它们都采用两个整数作为输入,并对每一位单独执行 AND/OR。要读出数字的第一位,您可以执行以下操作:
如您所见,您需要一个特殊的数字,其中仅设置我们感兴趣的位,这就是所谓的“位掩码”。在我们的例子中是
1
。要读出第二位,我们必须将位掩码中的一位向左“推”一位。我们可以使用左移运算符 ($number << 1
) 或将 our 乘以 2 来完成此操作。您可以对我们数字中的每一位进行此操作。我们的数字和位掩码的二进制 AND 导致要么为零,这意味着该位没有“设置”,要么导致非零整数,这意味着该位已设置。
如果您想设置其中一个位,可以使用按位或:
但是,当您想“清除”一位时,您必须采用不同的方式。
更通用的方法是:
乍一看可能有点神秘,但实际上很简单。
现在您可能已经发现位字段是一种相当低级的技术。这就是为什么我建议不要在 PHP 或数据库中使用它们。如果您想要一堆标志,那可能没问题,但对于其他任何事情,您真的不需要它们。
你发布的课程对我来说看起来有点特别。例如,诸如
... 之类的东西? true : false
是非常糟糕的做法。如果您想使用位字段,您最好定义一些常量并使用上述方法。想出一个简单的类并不难。我没有尝试这个答案的任何代码,但即使它不能开箱即用,它也应该让您开始。
请注意,每个位字段最多可包含 32 个值。
Bit fields are a very handy and efficient tool for dealing with flags or any set of boolean values in general.
To understand them you first need to know how binary numbers work. After that you should check out the manual entries on bitwise operators and make sure you know how a bitwise AND, OR and left/right shift works.
A bit field is nothing more than an integer value. Let's assume our bit field's size is fixed and only one byte. Computers work with binary numbers, so if the value of our number is
29
, you'll actually find0001 1101
in the memory.Using bitwise AND (
&
) and bitwise OR (|
) you can read out and set each bit of the number individually. They both take two integers as input and perform an AND/OR on each bit individually.To read out the very first bit of your number, you could do something like this:
As you can see you need a special number where only the bit we're interested in is set, that's the so called "bit mask". In our case it's
1
. To read out the second bit we have to "push" the one in the bitmask one digit to the left. We can do that with the left shift operator ($number << 1
) or by multiplying our by two.You can do that for every bit in our number. The binary AND of our number and the bit mask leads either to zero, which means the bit wasn't "set", or to a non-zero integer, which means the bit was set.
If you want to set one of the bits, you can use bitwise OR:
However, you'll have to go a different way when you want to "clear" a bit.
A more general approach would be:
At first it might look a bit cryptic, but actually it's quite easy.
By now you probably found out that bit fields are quite a low-level technique. That's why I recommend not to use them within PHP or databases.. If you want to have a bunch of flags it's probably ok, but for anything else you really don't need them.
The class you posted looks a bit special to me. For example, things like
... ? true : false
are veery bad practice. If you want to use bit fields, you're probably better off defining some constants and use the method described above. It's not hard to come up with a simple class.I didn't try any piece of code of this answer, but it should get you started even if it isn't working out of the box.
Note that you're limited to 32 values per bit field.
以下是定义位掩码的方法。
要检查位掩码是否存在(在本例中是在函数参数中),请使用按位 AND 运算符。
这是有效的,因为当您对两个字节(例如
00000001
和00010000
)进行“或”操作时,您会将两个字节放在一起:00010001
。如果将结果与原始掩码(00010001
并表示00000001
)进行 AND 运算,则您会得到一个掩码(如果存在)(在本例中为00000001
>)。否则,你会得到零。Here's how to define bitmasks.
To check if a bitmask is present (in this case in a function argument), use the bitwise AND operator.
This works because when you OR two bytes (say,
00000001
and00010000
), you get the two together:00010001
. If you AND the result and the original mask (00010001
and say,00000001
), you get a the mask if it's present (in this case00000001
). Otherwise, you get zero.