I'd separate the base user and roles class by having an intermediator between them.
$roles = $provider->roles($user);
This way class user
and class accessRole
do not have to know each other or any of their respective properties. class user
can happily live without access roles and class accessRole
isn't bound to $_userId. E.g. what would the userid be for an accessRole soley based on the time of day? (Ok, silly example. Hope you get the point). You may even translate roles for various subsystems without the need to carry all the specific (sub-)roles throughout the system.
$roles = $provider->convert($rolesBasedOnUser);
edit: (hopefully) short example....
I'm using a simple User class (no further interfaces or other kinds of abstraction) and there's no Roles "class", just a simple string array (for brevity's sake). But keep in mind that you can do a lot more decoupling ...if you like.
class User {
protected $id, $name;
public function __construct($id) {
$this->id = $id;
$this->name = 'user #'.$id;
}
public function getName() {
return $this->name;
}
public function getId() {
return $this->id;
}
}
interface UserRolesProvider {
public function roles(User $user);
}
Now you can have code that relies on the user class and the UserRolesProvider interface but let's you change the implementation of the provider without touching all the other code. Or it even only relies on the collection of Roles which let's you build/create/assemble the Roles as you like. Ok, let's have two (dummy) implementations of the provider interface.
class UserRolesA implements UserRolesProvider {
public function roles(User $user)
{
return 0===$user->getId()%2 ? array() : array('X');
}
}
class UserRolesB implements UserRolesProvider {
public function roles(User $user)
{
return 0!==$user->getId()%2 ? array() : array('X');
}
}
and some User objects
// "create" 6 users
$users = array_map( function($x) { return new User($x); }, range(1,6));
and something that uses both
function foo($users, UserRolesProvider $provider) {
foreach($users as $u) {
$roles = $provider->roles($u);
echo $u->getName(), ' ', join(',', $roles), " | ";
}
echo "\n";
}
foo($users, new UserRolesA);
foo($users, new UserRolesB);
prints
user #1 X | user #2 | user #3 X | user #4 | user #5 X | user #6 |
user #1 | user #2 X | user #3 | user #4 X | user #5 | user #6 X |
Not too impressive. But the point is you don't have to touch the User class or the code in function foo().
And the decoupling can go on and on ...if you like.
E.g. a registry that can answer to "I have some [type] here. Can you give me something that builds roles from it?"
Or maybe even "Can you build me a stub so that I can call fn($roles) as fn([type])?"