Я пытаюсь понять функцию, которая была написана кем-то другим, но мне трудно со вторым оператором if, который находится внутри цикла for. Может кто-нибудь объяснить логику здесь? Что на самом деле сравнивается?
Данные для таблицы CMS_ROLE имеют следующие столбцы: ID, ROLE_MASK, ROLE_KEY. Оба varchar (100). ROLE_MASK — это заголовок, такой как менеджер, автор, администратор и т. Д. ROLE_KEY — это номер, присвоенный ROLE_MASK.
1 | Менеджер | 1
2 | Автор | 4
3 | Admin | 9
function roleKeys($roleMask)
{
$roleKeys = array();
$this->queryBuilder
->select(array("ROLE_MASK", "ROLE_KEY"))
->from("CMS_ROLE");
$roles = $this->queryBuilder->execute()->fetchAll();
foreach ($roles as $role) {
if ($roleMask) {
if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];
} else if (!$role["ROLE_MASK"]) {
$roleKeys[] = $role["ROLE_KEY"];
}
}
return $roleKeys;
}
ОБНОВИТЬ:
Вот мой вывод var_dump. Все еще в замешательстве.
echo "intval role_mask : " ; var_dump(intval($role["ROLE_MASK"]));
echo "if statement : " ; var_dump( intval($roleMask & intval($role["ROLE_MASK"])));
echo "<br />-----------------<br />";
intval role_mask :
int 0
if statement :
int 0
-----------------
intval role_mask :
int 1
if statement :
int 1
-----------------
intval role_mask :
int 2
if statement :
int 0
-----------------
intval role_mask :
int 4
if statement :
int 0
-----------------
intval role_mask :
int 8
if statement :
int 0
-----------------
intval role_mask :
int 16
if statement :
int 0
-----------------
intval role_mask :
int 32
if statement :
int 32
-----------------
intval role_mask :
int 99
if statement :
int 97
-----------------
intval role_mask :
int 98
if statement :
int 96
-----------------
intval role_mask :
int 97
if statement :
int 97
-----------------
Ниже приведено простое объяснение того, как работает побитовый оператор, оно должно помочь вам понять, что программист намеревался сделать
Предположим следующие значения для переменных:
СЛУЧАЙ 1:
$roleMask = 5;
$role["ROLE_MASK"] = 5;
для оператора if:
if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];
состояние:
((intval($roleMask) & intval($role["ROLE_MASK"]) == intval($roleMask))
решается следующим образом:
5 in binary = 101
Затем 101 сравнивается с 101 по битам
побитовое И следует этим правилам:
1 compared to 1 = 1
1 compared to 0 = 0
0 compared to 0 = 0
0 compared to 1 = 0
это дает:
1 compared to 1 = 1
0 compared to 0 = 0
1 compared to 1 = 1
101 в десятичном виде это 5, так
(5 & 5) = 5
Оператор if становится
if ((5 & 5) == 5) $roleKeys[] = $role["ROLE_KEY"];
который разрешает
if (5 == 5) $roleKeys[] = $role["ROLE_KEY"];
СЛУЧАЙ 2:
$roleMask = 6;
$role["ROLE_MASK"] = 7;
для оператора if:
if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];
состояние:
((intval($roleMask) & intval($role["ROLE_MASK"]) == intval($roleMask))
решается следующим образом:
6 in binary = 110
7 in binary = 111
Затем 110 сравнивается с 111 по битам
следуя тем же правилам, что и выше, это дает:
1 compared to 1 = 1
1 compared to 1 = 1
0 compared to 1 = 0
110 в десятичном виде это 6, так
(6 & 7) = 6
Оператор if становится
if ((6 & 7) == 6) $roleKeys[] = $role["ROLE_KEY"];
который разрешает
if (6 == 6) $roleKeys[] = $role["ROLE_KEY"];
ДЕЛО 3:
$roleMask = 7;
$role["ROLE_MASK"] = 4;
для оператора if:
if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];
состояние:
((intval($roleMask) & intval($role["ROLE_MASK"]) == intval($roleMask))
решается следующим образом:
7 in binary = 111
4 in binary = 100
111 тогда сравнивается с 100 бит за битом
следуя тем же правилам, что и выше, это дает:
1 compared to 1 = 1
1 compared to 0 = 0
1 compared to 0 = 0
100 в десятичном виде это 4, так
(7 & 4) = 4
Оператор if становится
if ((7 & 4) == 7) $roleKeys[] = $role["ROLE_KEY"];
который разрешает
if (4 == 7) $roleKeys[] = $role["ROLE_KEY"];
В этом случае сравнение не проходит проверку .. надеюсь, это поможет
Если у вас есть набор флагов $flags
и немного маски $bitMask
способ проверить, установлены ли все биты в битовой маске:
if (($flags & $bitMask) == $bitMask)
Это выражение, которое вы имеете, за исключением аргументов &
поменялся местами (что не имеет значения).
Например, скажем, $flags
является 0x1110
а также $bitMask
является 0x0110
, Если вы И эти две ценности вместе, вы получите 0x0110
, Это проходит тест, так как это значение равно $bitMask
,
Теперь давайте скажем $flags
является 0x1110
а также $bitMask
является 0x0111
, ANDing те вместе производит 0x0110
, Это значение делает не матч $bitMask
, поэтому тест не пройден. Не все биты в битовой маске были установлены в переменной flags, а именно — самый правый бит.