What I kind of wanted to do is revisit the idea of a Domain Model for this problem. Perhaps we can completely forget about the storage mechanism and the Data Model for a minute. What would a Domain Model look like for this problem? Well, let's suppose we want to just model the following entities: User, Role, Permission (forgive my naming for a moment)? What would each class look like? What data would each class have? What behavior would each class have? Well, the core RBAC spec describes this relationship:
Code:
* * * *
User <-----------> Role <------------> Permission
We could have three classes: User, Permission, and Role.
PHP Code:
<?php
// Domain Object: User
class User {
var $id;
var $name;
var $roles;
function User() {}
function setId($id) {}
function getId() {}
function setName($name) {}
function getName() {}
function addRole(&$role) {}
function removeRole(&$role) {}
function hasRole(&$role) {}
function &getRoles() {}
}
// Domain Object: Role
class Role {
var $id;
var $name;
var $users;
var $permissions;
function Role() {}
function setId($id) {}
function getId() {}
function setName($name) {}
function getName() {}
function addUser(&$user) {}
function removeUser(&$user) {}
function hasUser(&$user) {}
function &getUsers() {}
function addPermission(&$permission) {}
function removePermission(&$permission) {}
function hasPermission(&$permission) {}
function &getPermissions() {}
}
// Domain Object: Permission
class Permission {
var $id;
var $name;
var $roles;
function Permission() {}
function setId($id) {}
function getId() {}
function setName($name) {}
function getName() {}
function addRole(&$role) {}
function removeRole(&$role) {}
function hasRole(&$role) {}
function &getRoles() {}
}
// Create a new user
$user =& new User();
$user->setName("John");
// Update the data model
$mapper =& new UserMapper();
$mapper->insert($user);
// Create a new role
$role =& new Role();
$role->setName("Administrator");
// Update the data model
$mapper =& new RoleMapper();
$mapper->insert($role);
// Create the many-to-many association between the two objects
$user->addRole($role);
$role->addUser($user); // <-- you don't really need to do this if you account for it in the User::addRole implementation $role->addUser($this)
// Update the data model
$mapper =& new UserMapper();
$mapper->update($user);
?>
Now, with a Domain Model like this you can definitely see there are several dependency relationships between the classes. You could employ lazy-loading for the dependent objects in each class. Also, the collections in each class could be identity maps.
Okay, so what about the persistence. Well, you could use the Association Table Mapping pattern from PoEAA. So each class would have a Mapper/Finder class associated with it to manage it's persistence. However, since there are dependencies between the classes, the Mappers would have to call each other in order to manage the persistence of the dependent objects.
I know it seems a little far-fetched, but I wanted to try to look at the problem from a different angle.
JT
Bookmarks