Jose Carlo Quilala
Jose Carlo Quilala

Reputation: 11

PHP Question about bitwise

I have a script like this

$job = array(
        1 => 'User',
        2 => 'Editor',
        4 => 'Supervisor',
        8 => 'Manager',
        10 => 'President');

$value = 18;

foreach($job as $key => $val)
{
   if($value & $key)
   {
      $job[] = $key;
      echo $val.', ';
   }
}

now what I want to achieve is that in the example above '18' system must only display the value as ' Manager, President, ' ( 10+8 = 18; )

But if you run the script, the system displays as Editor, President,

that's not all the arrays I've got, I have like 23 more array values

Sorry but I really can't explain it in english, hope you understand...

Upvotes: 1

Views: 514

Answers (4)

Brad Christie
Brad Christie

Reputation: 101614

<?php

  $flags = array(
    1   => 'User',       // 00000001 Note the place of the 1
    2   => 'Editor',     // 00000010
    4   => 'Supervisor', // 00000100
    8   => 'Manager',    // 00001000
    16  => 'President'   // 00010000
  );

  // permission we're going for
  $permissions = 16 + 8; // 00011000  again, note the 1's places.

  $levels = array();
  foreach ($flags as $level => $name)
  {
    if (($permissions & $level) == $level)
      $levels[] = $name;
  }
  echo implode(', ', $levels);

Output:

Manager, President

You want your values in powers of 2 so that, in binary, the corresponding flag matches the permission you're specifying.

The bit-wise AND (&) is saying (when it reaches Manager):

    $flags     $Pemissions   $flags
if (00001000 & 00011000) ==  00001000
if       (00001000)      ==  00001000 [true]

Basically, if the flag is set on both sides (both the value you're checking for and against) keep that bit. Then, make sure it still equals the value you're checking for. If it does, the user is set to that permission. An AND is only true when both the left and the right values have the bit(s) set.

Upvotes: 3

Yhn
Yhn

Reputation: 2815

Your problem is that 10 is not a 2^y variable.

10 = 2+8 (2^1 and 2^3), and thus will match values 2 and 8 respectively.

If you want to allow bitwise selection like you do; you need to pick 2^y values for your indexes (1, 2, 4, 8, 16, 32, etc).

Then you can safely add those values as selectors (e.g. 16+4 (20), 2+32(34) etc).

Upvotes: 1

RiaD
RiaD

Reputation: 47658

you should change 10 to 16 (1,2,4,8,16,32, ..) or you may cannot understand some number. Is 10=10 or 10=2+8

Upvotes: 0

Jon
Jon

Reputation: 437794

The value for President is wrong. To use a bitfield all numbers must be powers of two, so President should be 16 and not 10.

Note that 16 (decimal) is 0x10 (hex) -- perhaps setting the President value to 10 (decimal) was a copy/paste error?

Upvotes: 1

Related Questions