See here: Sf2: using a service inside an object
Maybe my answer here helps. He simply addresses this: how to "separate" the model from the level of resistance to the levels of the controller.
In your specific question, I would say that there is a "trick" ... what is a "group"? It's one"? or is it when it is connected with someone?
Your model classes might initially look like this:
UserManager (service, entry point for all others) Users User Groups Group Roles Role
UserManager will have methods for getting model objects (as said in this answer, you should never do new ). In the controller you can do this:
$userManager = $this->get( 'myproject.user.manager' ); $user = $userManager->getUserById( 33 ); $user->whatever();
Then ... User , as you say, there may be roles that can be assigned or not.
// Using metalanguage similar to C++ to show return datatypes. User { // Role managing Roles getAllRolesTheUserHasInAnyGroup(); void addRoleById( Id $roleId, Id $groupId ); void removeRoleById( Id $roleId ); // Group managing Groups getGroups(); void addGroupById( Id $groupId ); void removeGroupById( Id $groupId ); }
I simplified, of course, you can add Id, add Object, etc.
But when you think about it in "natural language" ... let's see ...
- I know that Alice belongs to photographers.
- I get an Alice object.
- I ask Alice about groups. I get a group of photographers.
- I ask photographers for roles.
More details:
- I know that Alice is a user id = 33, and she is in the group of Photographers.
- I ask Alice to contact UserManager through
$user = $manager->getUserById( 33 ); - I join a group of photographers through Alice, possibly with `$ group = $ user-> getGroupByName ('Photographers');
- I would like to see the roles of the group ... What should I do?
- Option 1: $ group-> getRoles ();
- Option 2: $ group-> getRolesForUser ($ userId);
The second is similar to redundant, as I got the group through Alice. You can create a new GroupSpecificToUser class that inherits from Group .
Like in a game ... what is a game? "Game" like "chess" in general? Or a specific “game” of “chess” with which you and I started yesterday?
In this case, $user->getGroups() will return a collection of GroupSpecificToUser objects.
GroupSpecificToUser extends Group { User getPointOfViewUser() Roles getRoles() }
This second approach will allow you to encapsulate there many other things that will appear sooner or later: is this user allowed to do something here? you can simply request a group subclass: $group->allowedToPost(); , $group->allowedToChangeName(); , $group->allowedToUploadImage(); etc.
In any case, you can avoid creating a taht weird class and just ask the user about this information, for example, the approach $user->getRolesForGroup( $groupId ); .
The model is not a resistance level.
I like to “forget” about design progress. Usually I sit with my team (or with myself, for personal projects) and spend 4 or 6 hours just thinking before writing any line of code. We are writing an API in dxt dxt. Then try adding, removing methods, etc.
A possible "starting point" API for your example may contain queries of any type of triangle:
User getId() getName() getAllGroups()
Developments
As stated in this article, I would also throw away events in the model,
For example, when deleting a role from a user in a group, I could find in the “listener” that if this was the last administrator, I can: a) cancel the removal of the role, b) allow it and leave the group without an administrator, c) allow it, but select a new administrator using users in the group, etc. or any other option suitable for you.
Similarly, perhaps a user can only belong to 50 groups (as on LinkedIn). Then you can simply throw the preAddUserToGroup event, and any spectacle can contain a set of rules prohibiting this when the user wants to join group 51.
This "rule" can explicitly go beyond the class "User", "Group" and "Role" and leave it in a higher level class that contains "rules" with which users can join or leave groups.
I highly recommend looking at a different answer.
Hope to help!
Xavi.