tags:

views:

283

answers:

2

I am trying to optimize my mysql table a little bit in order to have a slightly more manageable table. I would like to store user permissions in a bit field.

For example, a users permissions could be 0110 (I have a growing number of user permissions, so the length of this could be a bit longer)

The example might correspond to the following:

0: User cannot post news items on the website 1: User can post new articles on the website 1: User can edit any article on the website 0: User cannot remove articles from the website etc. (for other permissions)

If I have this stored in a mysql bit field. How can I manipulate this in PHP?

For example, in PHP is there an easy way to get the 3rd bit and see if it is a 0 or a 1?

Is there an easy way to set the 3rd bit to be a 0 or a 1?

+2  A: 

You can use bitwise operators.

For instance :

$bits = bindec('0110');
var_dump($bits & bindec('0100'));

Will get you "4" (i.e. non-zero -- which you can consider as "ok"), as the third bit in $bits is set.

And :

$bits = bindec('0010');
var_dump($bits & bindec('0100'));

Will get you 0 -- as the third bit in $bits is not set.


Of course, no need to call bindec each time -- I just used it here to make things easier to read ; my first example could be rewritten as something like this :

$bits = bindec('0110');
var_dump($bits & 1<<2);


And to make to code easier to understand, don't use such magic values, but use some constants ; for instance :

define('PERMISSION_TO_DO_X', 1);
define('PERMISSION_TO_DO_Y', 1<<1);
define('PERMISSION_TO_DO_Z', 1<<2);

And to use them :

$bits = bindec('0110');
if ($bits & PERMISSION_TO_DO_X) {
    echo "OK to do X<br />";
}
if ($bits & PERMISSION_TO_DO_Y) {
    echo "OK to do Y<br />";
}
if ($bits & PERMISSION_TO_DO_Z) {
    echo "OK to do Z<br />";
}

Which, here, gets you that kind of output :

OK to do Y
OK to do Z

Because :

  • the right-most bit is 0 (permission X not granted)
  • the second bit (starting from the right) is 1 : permission Y is granted
  • the third bit (still and always starting from the right) is 1 : permission Z granted
Pascal MARTIN
Thanks for your help! I implemented this slightly differently. But I used your general concept.
Brian
+1  A: 

Have you considered storing your permissions as an integer, with each permission a binary value (ie, 1,2,4,8,16), and you add together all their permissions. You can then check if they have a given permission using the & operator

Like so:

if ($accessLevel & $userPermissions)

That gives you a much more usable system than storing a binary number


As requested in comments, a little more information.

You would set up your users table to have an integer field to store your permissions. Each of your permission levels would have a binary multiple (don't know the correct term here) that corresponds with the value of a binary bit. For example:

Read - 1
Edit - 2
Create - 4
Delete - 8

And so on, as many as required. In order to create a users permission level, you OR the values together. Let's assume the above levels are stored in a class as static values, you would create it like so:

$newUser->Permissions = Permissions::Read | Permissions::Create;

Which gives you a user that can read and create, but not edit or delete.

To check if a user has permission to perform an action, you use AND:

if ($newUser->Permissions & Permissions::Read) {
    echo 'You can do this!';
}  else {
    echo 'You can't this!';
}

This gives you one simple database field, that's as extendible as you'll realistically need, and simple to use checks and changes. You might also want to consider storing permission levels in another table, etc, depending on what level of customization you might need.

mabwi
Could somebody expand on this for me a little please?
MrChrister