在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>';

}

?>

回答:

通常,位字段是一种非常方便有效的工具,用于处理标志或任何布尔值集。

要了解它们,您首先需要知道二进制数是如何工作的。之后,您应该查看按位运算符的手动输入,并确保您知道按位AND,OR和左/右移位的工作方式。

位域不过是一个整数值。假设我们的位字段的大小是固定的,只有一个字节。计算机使用二进制数字工作,因此,如果我们的数字值为29,您实际上会0001

1101在内存中找到。

使用按位AND(&)和按位OR(|),您可以读出并分别设置数字的每一位。它们都接受两个整数作为输入,并分别对每个位执行AND / OR。

要读出号码的第一位,可以执行以下操作:

  0001 1101 (=29, our number)

& 0000 0001 (=1, bit mask)

= 0000 0001 (=1, result)

如您所见,您需要一个特殊的数字,即仅设置我们感兴趣的位,即所谓的“位掩码”。在我们的情况下是1。要读出第二位,我们必须将位掩码中的一位“推”到左边一位。我们可以使用左移运算符($number

<< 1)或乘以2来实现。

  0001 1101

& 0000 0010

= 0000 0000 (=0, result)

您可以在我们的电话号码中做到这一点。我们的数字与位掩码的二进制与结果要么为零(表示未“置位”),要么为非零整数(即该位已置位)。

如果要设置一位,则可以使用按位或:

  0001 1101

| 0010 0000 (=32, bit mask)

= 0011 1101 (=29+32)

但是,当您想“清除”一点时,就必须走另一条路。

更一般的方法是:

// To get bit n

$bit_n = ($number & (1 << $n)) != 0

// Alternative

$bit_n = ($number & (1 << $n)) >> $n

// Set bit n of number to new_bit

$number = ($number & ~(1 << $n)) | ($new_bit << $n)

乍一看,它看起来有些神秘,但实际上很简单。

到现在为止,您可能已经发现位字段是一种很底层的技术。这就是为什么我建议不要在PHP或数据库中使用它们。如果您想要一堆标志可能没问题,但是对于其他任何事情,您实际上都不需要它们。

您发布的课程对我来说有点特殊。例如,类似... ? true :

false的事情非常糟糕。如果要使用位字段,最好定义一些常量并使用上述方法。上一堂简单的课并不难。

define('PERM_READ', 0);

define('PERM_WRITE', 1);

class BitField {

private $value;

public function __construct($value=0) {

$this->value = $value;

}

public function getValue() {

return $this->value;

}

public function get($n) {

return ($this->value & (1 << $n)) != 0;

}

public function set($n, $new=true) {

$this->value = ($this->value & ~(1 << $n)) | ($new << $n);

}

public function clear($n) {

$this->set($n, false);

}

}

$bf = new BitField($user->permissions);

if ($bf->get(PERM_READ)) {

// can read

}

$bf->set(PERM_WRITE, true);

$user->permissions = $bf->getValue();

$user->save();

我没有尝试此答案的任何代码,但是即使它开箱即用,它也应该使您入门。

请注意,每个位字段限制为32个值。

以上是 在PHP中使用位掩码进行设置? 的全部内容, 来源链接: utcz.com/qa/412201.html

回到顶部