newb Posted October 8, 2006 Share Posted October 8, 2006 how do u do ur usergroup permissions for if ur making a forum or cms.like root, admin, member?? or is there something more Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted October 8, 2006 Share Posted October 8, 2006 Have a permissions table or if it is permissions like "Is administrator?" then have fields in the group table for it. Quote Link to comment Share on other sites More sharing options...
newb Posted October 8, 2006 Author Share Posted October 8, 2006 yeah but im saying like, what usergroups do you use in the table Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted October 9, 2006 Share Posted October 9, 2006 Admin, (Guest), Members, (Unvalidated members), (Moderators) Quote Link to comment Share on other sites More sharing options...
neylitalo Posted October 9, 2006 Share Posted October 9, 2006 Well, since you're creating your own, you have complete and full control over the groups you create. I would suggest that you not create a fixed number of groups. Instead create a table `groups` and then you can create as many groups as you want to. And the specific groups you create will depend on the needs of your system - not everybody's needs are the same. Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 9, 2006 Share Posted October 9, 2006 I don't use groups, I specify permissions, then leave it for the administrator to modify a users permissions as they see fit.Each function of my site will have a permission associated with it, e.g. Posting has it's own, Editing will have it's own, User administration has it's own etc.I use bitwise comparison of an integer to store the permission and for checking. Quote Link to comment Share on other sites More sharing options...
newb Posted October 9, 2006 Author Share Posted October 9, 2006 ahh i c. Quote Link to comment Share on other sites More sharing options...
azuka Posted October 11, 2006 Share Posted October 11, 2006 I'm afraid some of the replies here are a bit vague. Is there somewhere I could get some tutorials [or a book] on implementing a PHP-based permissions system? Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 11, 2006 Share Posted October 11, 2006 Are you familiar with the background of bitwise operations? (I don't mean the bitwise operators, I am referring to the actual concept of using bits rather than a number as a whole) Quote Link to comment Share on other sites More sharing options...
newb Posted October 11, 2006 Author Share Posted October 11, 2006 nope Quote Link to comment Share on other sites More sharing options...
roopurt18 Posted October 11, 2006 Share Posted October 11, 2006 We'll start from the beginning.Computers are run by electrical current; the current is either there or it isn't. At the most fundamental levels, computers are only checking for the presence or lack of electrical current.This leads to the [i]b[/i]inary dig[i]it[/i], or bit. It is called a binary digit because it can only contain two possible values, 0 or 1. We call it a bit for short because we're lazy.Now, humans like to group things, it makes our lives easier. So we arbitrarily decided that 8 bits is called a byte, and 4 bytes is a word. (On some platforms a word could be more than 4 bytes, but that's irrelevant).PHP is different than most programming languages in that it isn't strongly typed, meaning that PHP converts relatively freely from an integer to a string to a floating point number. Other languages, like C, are very strongly typed. An integer can only interact with other data types that are a type of a number.Let's say that you're programming in C and that you happen to know that an integer in C is 1 word, which is the same as 4 bytes, which is the same as 32 bits.This means that you can think of any integer in C has being a string of length 32 where every place in the string is a 0 or a 1.For example:[code]0000 0000 0000 0000 0000 0000 0000 00000110 0010 0101 1111 0101 1000 0000 0001[/code]Let's throw a little bit of math in here for fun. Ignoring negative numbers, how many different numbers can we represent with such a string?Starting small...Bit string of length 1[code]01[/code]We can store two values in a string of length 1, notice that this is the same as 2^1Bit string of length 2[code]00011011[/code]We can store four values in a string of length 2, notice that this is the same as 2^2If we keep going, we find that we can store 2^n possible values in a bit string of length n. A bit string of length 32 can store 2^32 possible integers, which is why you can store some really large numbers in an integer variable! (Note to the more advanced reader: Yes, I'm ignoring sign bits. Don't get hung up on the details.)Explained in other words, every unique combination of a bit string is mapped to a unique integer. It's done through a mathematical formula which isn't really important for this discussion. But, rest assured that the following is true:0000 equals 00001 equals 10010 equals 20011 equals 3...1110 equals 141111 equals 15Now, I ask you a question. You're designing a website that has 16 permissions that are on or off. The user has permission to do this or the user doesn't.Here is one approach. You can create 16 integer variables. Set a variable to 0 to indicate the user doesn't have permission. Set a variable to 1 to indicate that they do. But what have you done, you've created 16 integers, each requiring 4 bytes of memory space. That's 64 total bytes of storage.Wouldn't it be really cool if we could store all those settings in just 4 bytes? The answer is yes and here's how you do it. You let each [b]bit[/b] of a single integer variable represent a permission. We count bit positions starting from 0 and from the right of the bit string.0101 - bit string3210 - bit positionIn position 0 (bottom) we have a value of 1 (top). In position 1 we have a value of 0. In position 2 we have a value of 1. In position 3 we have a value 0.If each position (0, 1, 2, & 3) represent a different permission, we can store 4 permissions in just 4 bits! This means that a 32 bit integer can be used to store 32 permissions that have an on or off setting.So how do we get at the individual bits? We use a mask. This would be a good point to look up a tutorial on hexadecimal, but for reference:0000 = 0 = 00001 = 1 = 10010 = 2 = 20011 = 3 = 30100 = 4 = 40101 = 5 = 50110 = 6 = 60111 = 7 = 71000 = 8 = 81001 = 9 = 9 We have now run out of 0-9 digits to represent values, so we use letters!1010 = 10 = A1011 = 11 = B1100 = 12 = C1101 = 13 = D1110 = 14 = E1111 = 15 = FWhat we have here is a mapping of 4 bits to a single value in the range of 0 through 9, A through F. You start a hexadecimal number with 0x and then end it with the digits (0-9, A-F).For example:The bit string:0110 0010 0101 1111 0101 1000 0000 0001is equivalent to the hex number:0x625F5801Look at that and absorb it until it makes sense; it's nothing more than a shorter way to write a bit string!You might be familiar with the [b]logical[/b] operators in PHP that compare values. These are && and ||. Well guess what, there are binary operators that do very similar tasks.& - From two values, make a bitwise comparison and return a composite result based on AND.For example:0111 & 1010 = 0010 - Notice that the result only contains a 1 where [b]both[/b] bit strings also contained a 1.| - From two values, make a bitwise comparison and return a composite result based on OR.For example:0101 | 1010 = 1111 - Notice that the result contains a 1 where [b]either[/b] bit string contained a 1.There is also a negation operator:~ From a single value, flip all of the bits.For example:~0101 = 1010 - Notice how all the bits changed to the opposite value of what they were.Now we can start packing multiple values into a single set of 32 bits (or an integer).[code]<?phpdefine('MOD_FORUMS', 0x00000001);define('DEL_THREAD', 0x00000002);...define('BOOT_USER', 0x80000000);var $perms = 0x00000000; // We init our current permissions to NONE// Let's turn on DEL_THREAD$perms = $perms | DEL_THREAD; // $perms now contains 0x00000002// Let's turn on MOD_FORUMS$perms = $perms | MOD_FORUMS; // $perms now contains 0x00000003 (the right most set of four bits is 0011, or 3 in hex)// Let's turn on our last permission$perms = $perms | BOOT_USER; // perms now contains 0x80000003// Now lets check for a permissionif($perms & MOD_THREAD){ // Check if the MOD_THREAD bit is turned on! echo 'user can mod a thread';}// Now let's turn a permission off// here we use the negation operator, we flip all of the bits in the permission constant and// AND it with the current set of permissions// Do it on paper and see why this turns off only one permission out of all of them :D$perms = $perms & ~MOD_THREAD;?>[/code]Wow! That's great for on or off type permissions.But now you might be thinking what if a permission has more than one value? You can still pack those types of settings using bitwise operators. I'll leave that as an exercise for you to research or discover on your own though.(EDIT) Because you turn permissions on with |, silly me. Quote Link to comment Share on other sites More sharing options...
newb Posted October 11, 2006 Author Share Posted October 11, 2006 what man.. u must be kidding me. there must be a shorter way to do this instead of all this binary and hexadecimal stuff to learn. my head is cracking. Quote Link to comment Share on other sites More sharing options...
neylitalo Posted October 11, 2006 Share Posted October 11, 2006 [quote author=roopurt18 link=topic=110890.msg450649#msg450649 date=1160602201]Now, humans like to group things, it makes our lives easier. So we arbitrarily decided that 8 bits is called a byte, and 4 bytes is a word. (On some platforms a word could be more than 4 bytes, but that's irrelevant).[/quote]I just had to nitpick."We" didn't decide anything - IBM decided. When IBM was the only company successfully making computers, their machines used 8-bit bytes. To maintain compatibility with the old IBM equipment, they simply continued using 8-bit bytes, and when other companies jumped in, they made their equipment use 8-bit bytes to maintain compatibility with IBM equipment. And a word is simply the amount of bits a processor can handle at one time, not 4 bytes and that's it. 32-bit (4 byte) processors are simply the most common right now among end-users.And newb, this is one of the easiest ways to do user permissions. One 'requirement' for being in this business is that you have to be willing to learn. And if you're not willing to learn how binary and hex work, then you'd better find a different occupation/hobby. Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 12, 2006 Share Posted October 12, 2006 Don't have to use hex, can stick with decimal..[code]<?phpif (!($perm ^ 2)){ $perm = $perm | 2;}?>[/code] Quote Link to comment Share on other sites More sharing options...
roopurt18 Posted October 12, 2006 Share Posted October 12, 2006 I used "we" as in us, the human species, not as in you and me. I could very well argue that by not doing anything to change the norm that we have also decided to do this as well though. And I did make a somewhat clouded reference to the size of a word being platform dependent.Binary and hex are so fundamental to computing and programming, shame to any programmer that doesn't understand them. And really, they're not all that difficult. Quote Link to comment Share on other sites More sharing options...
roopurt18 Posted October 12, 2006 Share Posted October 12, 2006 I recommend using named constants to represent the values of your permissions and not sticking $perm ^ 2 all over the place. Also, hex is more convenient as you add more permissions. You might know the value of 2^11 or 2^12 off the top of your head, but after that you're gonna need a calculator. Not to mention when you look at the code later you're going to go, "What the Hell does $perm ^ 2197987252197 do again?" Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 12, 2006 Share Posted October 12, 2006 Constants break encapsulation.Not to mention my example, was merely nothing but that... an example.For a real world example taken from a class:[code]<?phppublic function checkPermision($perm){ return (bool) $this->_permissions ^ $perm;}?>[/code]Hex is not more convinient, it's less readable.It's not hard to read.. 1, 2, 4, 8, 16, 32, 64.. etc. Quote Link to comment Share on other sites More sharing options...
roopurt18 Posted October 12, 2006 Share Posted October 12, 2006 Like I said, the first 12 or so are not difficult to read. But what about when you get up to your 16th or 21st permission?Constants do not break encapsulation. It is much easier 6 months later to read:[code]if($perm & _MOD_FORUMS){}[/code]than[code]if( $perm & 2097152 ){}[/code]Not to mention repeatedly typing 2097152 through out your code, what if you fat finger an 8 instead of a 7? It will be very hard to catch.Use constants. Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 12, 2006 Share Posted October 12, 2006 You need to learn what encapsulation is, constants most definitely do break it. Quote Link to comment Share on other sites More sharing options...
azuka Posted October 12, 2006 Share Posted October 12, 2006 Do we have to argue about constants breaking encapsulation? What if [using PHP 5's features] you create a class with a static array and build static functions that allow you to add and retrieve permission 'constants' ie array keys? Everyone decides what's best for him and works with it.As for the tutorial, I do understand binary and hex but never thought of the bitwise operators this way. Thanks for the [url=http://www.phpfreaks.com/forums/index.php/topic,110890.msg450649.html#msg450649]tutorial[/url]. Now I know just what to do to implement a permission-based system. Quote Link to comment Share on other sites More sharing options...
roopurt18 Posted October 12, 2006 Share Posted October 12, 2006 Le sigh, this is what I think of when you say encapsulation:http://en.wikipedia.org/wiki/Information_hidingPlease explain to me how this breaks the concept of encapsulation:[code]<?php // NPermissions.php // a simple example of a permission system // define our permission constants define( '_PERM_MOD_THREAD', 0x00000001 ); define( '_PERM_MOV_THREAD', 0x00000002 ); define( '_PERM_DEL_THREAD', 0x00000004 ); define( '_PERM_BAN_USER', 0x00000008 ); define( '_PERM_UNBAN_USER', 0x00000010 ); // more constants would follow depending on the module // In this example, I'm going to define a class that will not be instantiated. // Instead, the class is being used to create a namespace. // The assumption for the functions within the class is that the user // permissions are loaded from a DB elsewhere in the program. The first // param of the functions is this value, named $user_perms class NPermissions{ // $user_perms - current user permissions // RETURN: true if user has permission, false otherwise function Can_ModThread($user_perms){ return $user_perms & _PERM_MOD_THREAD; } // $user_perms - current user permissions // Update user's permissions to allow modding of a thread function Set_ModThread($user_perms){ return $user_perms | _PERM_MOD_THREAD; } // $user_perms - current user permissions // Update user's permissions to not allow thread modding function Rem_ModThread($user_perms){ return $user_perms & ~_PERM_MOD_THREAD; } // You would continue in this manner for each of your permissions // and possibly provide a few more utility functions as the case may // be. }?>[/code][code]<?php // AnotherFile.php // Meanwhile, in another part of the city... require_once('NPermissions.php'); // Build our forums $Posts = GetForumPosts(); if(is_array($Posts) && count($Posts)){ foreach($Posts as $Post){ // .. some code if(NPermissions::Can_ModThread($User->GetPerms())){ $html .= Link_ModThread(); } // .. some more code } }?>[/code]I have to say that's pretty neat, simple, and easy to maintain. 6 months later when you [i]do[/i] need to change the implementation, you can update the constants, do away with the constants, or whatever you want. Just as long as you keep the [i]interface[/i] the same, nothing else in the program breaks.Is this not what encapsulation is? If this fits your definition of encapsulation, I would be curious how the constants are breaking it. If it's not, I'd love for you to clarify. Quote Link to comment Share on other sites More sharing options...
redbullmarky Posted October 12, 2006 Share Posted October 12, 2006 guys guys - back on topic please ;D the topic of encapsulation seems very irrelevent to the objective, as it's not ESSENTIAL to obey these 'rules' for what newb first asked. (although i'm with roopurt anyway a bit actually on this one. the idea of not using global constants or functions as it breaks 'encapsulation' seems slightly contradicted by using php's own built in functions, constants, etc.)i'm following this topic myself as i'm keen to find out more - so would be good if the initial question got answered without over complication ;) Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 12, 2006 Share Posted October 12, 2006 [quote author=roopurt18 link=topic=110890.msg451025#msg451025 date=1160674959]Le sigh, this is what I think of when you say encapsulation:http://en.wikipedia.org/wiki/Information_hidingPlease explain to me how this breaks the concept of encapsulation:[code]<?php // NPermissions.php // a simple example of a permission system // define our permission constants define( '_PERM_MOD_THREAD', 0x00000001 ); define( '_PERM_MOV_THREAD', 0x00000002 ); define( '_PERM_DEL_THREAD', 0x00000004 ); define( '_PERM_BAN_USER', 0x00000008 ); define( '_PERM_UNBAN_USER', 0x00000010 ); // more constants would follow depending on the module // In this example, I'm going to define a class that will not be instantiated. // Instead, the class is being used to create a namespace. // The assumption for the functions within the class is that the user // permissions are loaded from a DB elsewhere in the program. The first // param of the functions is this value, named $user_perms class NPermissions{ // $user_perms - current user permissions // RETURN: true if user has permission, false otherwise function Can_ModThread($user_perms){ return $user_perms & _PERM_MOD_THREAD; } // $user_perms - current user permissions // Update user's permissions to allow modding of a thread function Set_ModThread($user_perms){ return $user_perms | _PERM_MOD_THREAD; } // $user_perms - current user permissions // Update user's permissions to not allow thread modding function Rem_ModThread($user_perms){ return $user_perms & ~_PERM_MOD_THREAD; } // You would continue in this manner for each of your permissions // and possibly provide a few more utility functions as the case may // be. }?>[/code][code]<?php // AnotherFile.php // Meanwhile, in another part of the city... require_once('NPermissions.php'); // Build our forums $Posts = GetForumPosts(); if(is_array($Posts) && count($Posts)){ foreach($Posts as $Post){ // .. some code if(NPermissions::Can_ModThread($User->GetPerms())){ $html .= Link_ModThread(); } // .. some more code } }?>[/code]I have to say that's pretty neat, simple, and easy to maintain. 6 months later when you [i]do[/i] need to change the implementation, you can update the constants, do away with the constants, or whatever you want. Just as long as you keep the [i]interface[/i] the same, nothing else in the program breaks.Is this not what encapsulation is? If this fits your definition of encapsulation, I would be curious how the constants are breaking it. If it's not, I'd love for you to clarify.[/quote]The constants are references to information outside of the 'capsule' that is a module.. thus: encapsualtion broken. Hard to understand? Quote Link to comment Share on other sites More sharing options...
roopurt18 Posted October 12, 2006 Share Posted October 12, 2006 So you're saying if you replace the constants with literals it makes all the difference? It would be the same thing.The reality is every single, separate module needs to define it's own permission constants that can be imported / referenced by a central controller. If you are designing a modular site with forums and photo galleries, each of those modules is likely to have it's own permissions. It is impossible for the controller to store those preferences within the same 16, 32, ..., n-bit field as the modules will step on each other.The reality is that every single module will need to define it's own permission system to be used only within that module.Every module will also need to provide a mechanism, designed by the controller, of exporting those preferences so that the controller, and not the module, can set preferences up for specific users or groups of users.Encapsulation is not broken. The forum module's constants only exist within that module, the photo gallery module's constants only exist within that module, etc. The only thing the controller ever needs to know is that this particular user logged in right now has a forum permission of 0xA0F2E0D8 and a photo gallery permission of 0x000013ABWhen did I ever say that all constants across all modules will all be placed in some central file? The situation called for a simple explanation of how bitwise operators could be used to pack multiple values into a single field. Quote Link to comment Share on other sites More sharing options...
Jenk Posted October 12, 2006 Share Posted October 12, 2006 Where did I specify "literals instead of constants"?Encapsulation is broken. Re-read the link you posted - the first paragraph says it all.You are bypassing all interfaces to your class, so you can stop mentioning "it's part of the interface" Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.