tags:

views:

95

answers:

2

Hi,

how do you design your objects lets say you have an object user and an object access_role. The user is stored in users table in an sql database, the access_role knows the user_id and is stored in an sql database.

    class user() {

    protected $_name;
    protected $_id;
    protected $_age;
    protected $_password;

    public function getName();
    public function getId();
    public function getAge();
    public function getPassword();

    public function setName();
    public function setId();
    public function setAge();
    public function setPassword();

    //sql query
    public function read(){}; 


    }

    class accessRole {

    protected $_accessRole;
    protected $_userId;

    public function setAccessRole();
    public function setUserId();
    public function getAccessRole();
    public function getUserId();

    }

If i want the access role for the user in do an query in sql. But how do you connect both objects, so that something like:

$u = new User();
$u->getAccessRole();

will work? I hope someone understands my question..

+2  A: 

I would typically pass the user ID to the constructor of the user class, and have this constructor create a local access role object:

class user() {

    protected $accessRole;

    function __construct($idUser) {
        $this->accessRole = new accessRole();
        $this->accessRole->setUserId($idUser);
        ...
    }

If initializing an access role object involves expensive operations and we do not always need the object, then we should find a way to delay its creation. What do you think?

Tom Bartel
+3  A: 

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 usercan 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])?"

VolkerK
Sounds interessting, can you explain this approach in detail please?
ArneRie
Looks like this is an exclusively German discussion... ;-)
Tom Bartel
still not clear for me (-:
ArneRie
It's completely possible I'm overdoing it, adding complexity you really don't need ;-)
VolkerK
@Tom: ...and please don't mention the war ;-) http://en.wikipedia.org/wiki/The_Germans
VolkerK
@Volker: HAHA :D
Tom Bartel