PHP Bitwise compare values from database with an array

Actually i would like to compare some values in a table with an array and output the key with has equal value of the array. Problem is: the values in the database are bitwise if i am right. Not sure if it is the right explanation in english.

Example: and here some example values form the table 1,65,2081,2145,18497,32769 65 contains 64 which is "UR_LEAD" and 1 which is "UR_SWP"

Here the array which i would like to compare with:

$userrights_array = array(
"UR_SWP"           => 1,
"UR_BUHA"          => 2,
"UR_AZ"            => 4,
"UR_SA"            => 8,
"UR_FIDI"          => 16,
"UR_ADMIN"         => 32,
"UR_LEAD"          => 64,
"UR_AZ_EVENT"      => 128,
"UR_SA_COMPLIANCE" => 256,
"UR_CH"            => 512,
"UR_USERMOD"       => 1024,
"UR_SWP_GL"        => 2048,
"UR_MEDB"          => 4096,
"UR_SWP_GP"        => 8192,
"UR_STAFF_DEPT"    => 16384,
"UR_MEET_KEYUSER"  => 32768,
"UR_MEET_ADMIN"    => 65536
);

Here the example to loop through the array and actually a fakeresult from the database to simplyfy the code.

$fakerow = 256;
foreach ($userrights_array as $key => $value) {
  if ($value == $fakerow) {
    print_r($key);
  }
};

What i need now is a solution to not just print out the value of the database but do an operation that compares the value from the array with the one in the database and check which fits for example into 65.

Guess i have to do the comparison in the if section but no idea how to.

Output should be like "UR_SWP" + "UR_LEAD"

The actual result in my form looks like this:

preview of the table

Answer

Solution:

If you want to print out permissions in words, you can first create a map of values with permissions in text using an array_flip(). Key point here is to collect permissions whose bit is set as 1 in the current permission.

Now, just convert the current permission value at hand to binary and collect the appropriate permission for a particular power of 2 and print out the result.

<?php

$userrights_array = array(
    "UR_SWP"           => 1,
    "UR_BUHA"          => 2,
    "UR_AZ"            => 4,
    "UR_SA"            => 8,
    "UR_FIDI"          => 16,
    "UR_ADMIN"         => 32,
    "UR_LEAD"          => 64,
    "UR_AZ_EVENT"      => 128,
    "UR_SA_COMPLIANCE" => 256,
    "UR_CH"            => 512,
    "UR_USERMOD"       => 1024,
    "UR_SWP_GL"        => 2048,
    "UR_MEDB"          => 4096,
    "UR_SWP_GP"        => 8192,
    "UR_STAFF_DEPT"    => 16384,
    "UR_MEET_KEYUSER"  => 32768,
    "UR_MEET_ADMIN"    => 65536
);

$userrights_array_flipped = array_flip($userrights_array);

foreach([1,65,2081,2145,18497,32769] as $val){
    $pow_2 = 1;
    $rights = [];
    while($val > 0){
        $d = $val % 2;
        if($d == 1 && isset($userrights_array_flipped[$pow_2])){
            $rights[] = $userrights_array_flipped[$pow_2];
        }
        $pow_2 <<= 1;
        $val >>= 1;
    }
    
    echo implode(",",$rights),PHP_EOL;
} 

Answer

Solution:

A "Bitwise AND" (&) operator is an option:

<?php
$userrights = array(
    "UR_SWP"           => 1,
    "UR_BUHA"          => 2,
    "UR_AZ"            => 4,
    "UR_SA"            => 8,
    "UR_FIDI"          => 16,
    "UR_ADMIN"         => 32,
    "UR_LEAD"          => 64,
    "UR_AZ_EVENT"      => 128,
    "UR_SA_COMPLIANCE" => 256,
    "UR_CH"            => 512,
    "UR_USERMOD"       => 1024,
    "UR_SWP_GL"        => 2048,
    "UR_MEDB"          => 4096,
    "UR_SWP_GP"        => 8192,
    "UR_STAFF_DEPT"    => 16384,
    "UR_MEET_KEYUSER"  => 32768,
    "UR_MEET_ADMIN"    => 65536
);
$rows = array(1, 65, 2081, 2145, 18497, 32769);

foreach ($rows as $row) {
    echo $row.": ";
    foreach ($userrights as $key => $userright) {
        if ($userright & $row) {
            echo $key.", ";
        }
    };
    echo "<br>";
}
?>

If you want to store the results in a string variable or an array, this may help:

<?php
...

// Store the output as a text
$output = "";
foreach ($rows as $row) {
    $output .= ($output === "" ? "" : ", ");
    foreach ($userrights as $key => $userright) {
        if ($userright & $row) {
            $output .= ($output === "" ? "" : " ") . $key;
        }
    };
}
echo $output;
echo "<br>";

// Store the output as an array
$output = array();
foreach ($rows as $row) {
    $s = "";
    foreach ($userrights as $key => $userright) {
        if ($userright & $row) {
            $s .= ($s === "" ? "" : " ") . $key;
        }
    };
    $output[] = $s;
}
echo print_r($output, true);
echo "<br>";
?>

Results:

1: UR_SWP,
65: UR_SWP, UR_LEAD,
2081: UR_SWP, UR_ADMIN, UR_SWP_GL,
2145: UR_SWP, UR_ADMIN, UR_LEAD, UR_SWP_GL,
18497: UR_SWP, UR_LEAD, UR_SWP_GL, UR_STAFF_DEPT,
32769: UR_SWP, UR_MEET_KEYUSER,

UR_SWP, UR_SWP UR_LEAD, UR_SWP UR_ADMIN UR_SWP_GL, UR_SWP UR_ADMIN UR_LEAD UR_SWP_GL, UR_SWP UR_LEAD UR_SWP_GL UR_STAFF_DEPT, UR_SWP UR_MEET_KEYUSER

Array ( 
   [0] => UR_SWP 
   [1] => UR_SWP UR_LEAD 
   [2] => UR_SWP UR_ADMIN UR_SWP_GL 
   [3] => UR_SWP UR_ADMIN UR_LEAD UR_SWP_GL 
   [4] => UR_SWP UR_LEAD UR_SWP_GL UR_STAFF_DEPT 
   [5] => UR_SWP UR_MEET_KEYUSER 
)

Source