Почему я должен использовать поразрядную / битовую маску в PHP?

Лично, мне обычно не нравятся возвращаемые параметры по ряду причин:

  • это не всегда очевидно в вызове, какие параметры являются ins и который является outs
  • , обычно необходимо создавать локальную переменную для ловли результата, в то время как возвращаемые значения могут использоваться встроенные (который может или не может быть хорошей идеей, но по крайней мере у Вас есть опция)
  • , это кажется инструментом для очистки мне для имения "в двери" и "дверь" в функцию - все исходные данные входят здесь, все выводы прибывают туда
  • , мне нравится сохранять мои списки аргументов максимально короткими

, у меня также есть некоторое резервирование о методе пары/кортежа. Главным образом часто нет никакого естественного порядка к возвращаемым значениям. Как читатель кода, чтобы знать, является ли result.first частным или остатком? И лицо, осуществляющее внедрение могло изменить порядок, который повредит существующий код. Это особенно коварно, если значения являются тем же типом так, чтобы никакая ошибка компилятора или предупреждение не были бы сгенерированы. На самом деле эти аргументы относятся к возвращаемым параметрам также.

Вот другой пример кода, этот немного менее тривиальный:

pair<double,double> calculateResultingVelocity(double windSpeed, double windAzimuth,
                                               double planeAirspeed, double planeCourse);

pair<double,double> result = calculateResultingVelocity(25, 320, 280, 90);
cout << result.first << endl;
cout << result.second << endl;

это печатает groundspeed и курс, или курс и groundspeed? Это не очевидно.

Выдерживают сравнение с этим:

struct Velocity {
    double speed;
    double azimuth;
};
Velocity calculateResultingVelocity(double windSpeed, double windAzimuth,
                                    double planeAirspeed, double planeCourse);

Velocity result = calculateResultingVelocity(25, 320, 280, 90);
cout << result.speed << endl;
cout << result.azimuth << endl;

я думаю, что это более ясно.

, Таким образом, я думаю, моим предпочтительным вариантом в целом является метод структуры. Идея пары/кортежа вероятна отличное решение в определенных случаях. Я хотел бы избежать возвращаемых параметров, если это возможно.

18
задан Anthony 24 March 2012 в 16:31
поделиться

6 ответов

Почему бы просто не сделать это ...

define('PERMISSION_DENIED', 0);
define('PERMISSION_READ', 1);
define('PERMISSION_ADD',  2);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 8);

//run function
// this value would be pulled from a user's setting mysql table
$_ARR_permission = 5;

if($_ARR_permission & PERMISSION_READ) {
    echo 'Access granted.';
}else {
    echo 'Access denied.';
}

Вы также можете создать множество произвольных комбинаций разрешений, если используете биты ...

$read_only = PERMISSION_READ;
$read_delete = PERMISSION_READ | PERMISSION_DELETE;
$full_rights = PERMISSION_DENIED | PERMISSION_READ | PERMISSION_ADD | PERMISSION_UPDATE | PERMISSION_DELETE;

//manipulating permissions is easy...
$myrights = PERMISSION_READ;
$myrights |= PERMISSION_UPDATE;    // add Update permission to my rights
41
ответ дан 30 November 2019 в 05:54
поделиться

Первый позволяет людям иметь множество разрешений - например, чтение / добавление / обновление. Во втором примере у пользователя есть только PERMISSION_UPDATE .

Побитовое тестирование работает путем проверки битов на значения истинности.

Например, двоичная последовательность 10010 будет идентифицировать пользователя с PERMISSION_DELETE и PERMISSION_READ (бит, идентифицирующий PERMISSION_READ - это столбец для 2, бит, идентифицирующий PERMISSION_DELETE ), [столбец для 116811] 10010 в двоичном формате равно 18 в десятичном (16 + 2 = 18). Ваш второй пример кода не позволяет вам проводить такое тестирование. Вы можете выполнять проверки более высокого стиля, но это предполагает, что все с PERMISSION_DELETE также должны иметь PERMISSION_UPDATE ,

10
ответ дан 30 November 2019 в 05:54
поделиться

Может быть, это просто потому, что я не очень часто использую битовые маски, но я нахожу это на таком языке, как PHP, где производительность разработчика и читаемость кода более важны, чем скорость или использование памяти (в определенных пределах, очевидно), нет реальной причины использовать битовую маску.

Почему бы вместо этого не создать класс, который отслеживает такие вещи, как разрешения, зарегистрированные пользователи и так далее? Назовем это Auth. Затем, если вы хотите проверить, есть ли у пользователя разрешение, вы можете создать метод HasPermission. например,

if(Auth::logged_in() && Auth::currentUser()->hasPermission('read'))
    //user can read

, тогда, если вы хотите проверить, есть ли у них какая-либо комбинация разрешений:

if(Auth::logged_in() && Auth::currentUser()->hasAllPermissions('read', 'write'))
    //user can read, and write

или если вы хотите проверить, есть ли у них какие-либо разрешения из определенной группы:

if(Auth::logged_in() && Auth::currentUser()->hasAnyPermissions('read', 'write'))
    //user can read, or write

Конечно, это может быть не плохая идея определять константы, такие как PERMISSION_READ, которые вы можете просто определить как строку 'read' и т. д.

Мне этот подход легче читать, чем битовые маски, потому что имена методов говорят вам, что именно вы ищем.

10
ответ дан 30 November 2019 в 05:54
поделиться

Правка : перечитывая вопрос, похоже, что разрешения пользователя возвращаются из вашей базы данных в битовом поле. В этом случае вам придется использовать побитовые операторы. Пользователь с разрешением в базе данных 5 имеет PERMISSION_READ и PERMISSION_DENIED , поскольку (PERMISSION_READ & 5)! = 0 и ] (PERMISSION_DENIED & 5)! = 0 . У него не было бы PERMISSION_ADD , потому что (PERMISSION_ADD & 5) == 0

Есть ли в этом смысл? Все сложные вещи в вашем побитовом примере выглядят ненужными.


Если вы не полностью понимаете побитовые операции, не используйте их. Это только вызовет много головных болей. Если тебе с ними комфортно, затем используйте их там, где считаете их подходящими. Вы (или тот, кто написал побитовый код), похоже, не полностью понимаете побитовые операции. С этим связано несколько проблем, таких как использование функции pow () , которая свела бы на нет любое улучшение производительности. (Вместо pow (2, $ n) , вы должны использовать, например, побитовое 1 << $ n .)

Тем не менее, два фрагмента кода делают похоже, не делают то же самое.

1
ответ дан 30 November 2019 в 05:54
поделиться

Попробуйте использовать то, что есть в bit.class. php на http://code.google.com/p/samstyle-php-framework/source/browse/trunk/class/bit.class.php

Проверка на конкретный бит:

<?php

define('PERMISSION_DENIED', 1);
define('PERMISSION_READ', 2);
define('PERMISSION_ADD',  3);
define('PERMISSION_UPDATE', 4);
define('PERMISSION_DELETE', 5);


if(bit::query($permission,PERMISSION_DENIED)){
echo 'Your permission is denied';
exit();
}else{
// so on
}

?>

И чтобы включить и выключить:

<?php

$permissions = 8;
bit::toggle(&$permissions,PERMISSION_DENIED);

var_dump($permissions); // outputs int(9)

?>
1
ответ дан 30 November 2019 в 05:54
поделиться

Думаю, первый пример дает вам больше контроля над тем, какие именно права есть у пользователя. Во втором у вас просто есть «уровень» пользователя; предположительно более высокие уровни наследуют все разрешения, предоставленные пользователю более низкого «уровня», поэтому у вас нет такого точного контроля.

Кроме того, если я правильно понял, строка

if($user_permission_level === 4)

означает, что только пользователи с ровно уровнем разрешений 4 имеют доступ к действию - конечно, вы захотите проверить, что у пользователей есть на как минимум того уровня?

0
ответ дан 30 November 2019 в 05:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: