PHP класс маски


Я пытался узнать больше об использовании бит/разряды/битовая маска, или как вы их называете именно на PHP для разных настройках и разрешениях. С помощью других людей, я придумал этот класс. Он прошел долгий путь с момента, когда я это начал, но я ищу какие-либо идеи о том, как усовершенствовать его дальше.

<?php

abstract class BitField {

    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);
    }
}

class UserPermissions_BitField extends BitField
{
    const PERM_READ = 0;
    const PERM_WRITE = 1;
    const PERM_ADMIN = 2;
    const PERM_ADMIN2 = 3;
    const PERM_ADMIN3 = 4;
}

class UserPrivacySettings_BitField extends BitField
{
    const PRIVACY_TOTAL = 0;
    const PRIVACY_EMAIL = 1;
    const PRIVACY_NAME = 2;
    const PRIVACY_ADDRESS = 3;
    const PRIVACY_PHONE = 4;
}
?>

Пример использования:

<?php
$user_permissions = 0; //This value will come from MySQL or Sessions
$bf = new UserPermissions_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


// 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>';
}

?>


3307
4
задан 29 марта 2011 в 12:03 Источник Поделиться
Комментарии
2 ответа

Вы вроде хватает точки с помощью битовых масок.

Вы должны использовать простые битовые операции.

Если каждый бит представляет настройки конфиденциальности, а затем операции должны быть:


  1. Проверить, если значение, используя оператор&.

    ($этом->значение & $н) == $н;


  2. Установите значение, используя оператор | (или |=).

    $этом->значение |= $н;


  3. Сброс значения с помощью оператора (или &=).

    $этом->значение &= ~$н;


И тогда ваши ценности должны быть полномочия 2. Обычно 0 сохраняется нулевое значение или недопустимое значение.

class UserPrivacySettings_BitField extends BitField
{
const PRIVACY_EMAIL = 1;
const PRIVACY_NAME = 2;
const PRIVACY_ADDRESS = 4;
const PRIVACY_PHONE = 8;
const PRIVACY_ALL = 15;
}

Теперь первые 4 значения соответствует 1 бит. И вы можете воспользоваться PRIVACY_ALL с помощью комбинации из всех остальных ценностей.

т. е. в битах

PRIVACY_EMAIL   = 0001
PRIVACY_NAME = 0010
PRIVACY_ADDRESS = 0100
PRIVACY_PHONE = 1000
PRIVACY_ALL = 1111

Таким образом, если вы установить все значения по отдельности, а затем проверить PRIVACY_ALL, что будет иметь значение true.

Вот пересмотренный код, с примерами в конце.

<?php
abstract 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 & $n) == $n;
}

public function set($n) {
$this->value |= $n;
}

public function clear($n) {
$this->value &= ~$n;
}
}

class UserPrivacySettings_BitField extends BitField
{
const PRIVACY_EMAIL = 1;
const PRIVACY_NAME = 2;
const PRIVACY_ADDRESS = 4;
const PRIVACY_PHONE = 8;
const PRIVACY_ALL = 15;
}

$bf = new UserPrivacySettings_BitField();
echo "Setting PRIVACY_EMAIL<br/>";
$bf->set(UserPrivacySettings_BitField::PRIVACY_EMAIL);
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_EMAIL));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_NAME));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_ADDRESS));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_PHONE));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_ALL));
echo "Setting PRIVACY_NAME<br/>";
$bf->set(UserPrivacySettings_BitField::PRIVACY_NAME);
echo "Setting PRIVACY_ADDRESS<br/>";
$bf->set(UserPrivacySettings_BitField::PRIVACY_ADDRESS);
echo "Setting PRIVACY_PHONE<br/>";
$bf->set(UserPrivacySettings_BitField::PRIVACY_PHONE);
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_EMAIL));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_NAME));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_ADDRESS));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_PHONE));
var_dump($bf->get(UserPrivacySettings_BitField::PRIVACY_ALL));

В качестве примера, посмотрите на значения констант ошибка в PHP. http://php.net/manual/en/errorfunc.constants.php

6
ответ дан 29 марта 2011 в 12:03 Источник Поделиться

Если вы действительно хотите пить РНР "Кул-Эйд", вы могли бы реализовать интерфейса ArrayAccess интерфейс таким образом, чтобы клиенты могли использовать

$bf[UserPermissions_BitField::PERM_READ] = true;
...
if ($bf[UserPermissions_BitField::PERM_READ]) { ... }

Учитывая, что ты инкапсуляция целое реализации битовое поле, вы, вероятно, следует добавить $размер параметра в конструктор, чтобы разрешить методов доступа, чтобы убедиться, что дали $поле находится вблизи границы.

4
ответ дан 29 марта 2011 в 01:03 Источник Поделиться