|
My question is - Is it a better MVC architecture to have a 1 to 1
relationship for a controller to access the model and the view, or since in a case where all relationships stem from a single model - just make the one controller have all the actions, but pull data from the related models needed together to then send to a view. Here is some code to help illustrate what I am talking about. ( I removed a lot of configuration details, because it is not relevant for the architecture discussion) Organization Model $hasMany = array('OrganizationRole', 'Address', 'MemberRelationship'); $belongsTo = array('User'); OrganizationRole Model $hasMany = array('OrganizationPermission', 'MemberRelationship'); $belongsTo = array('Organization'); MemberRelationship Model $belongsTo = array('Organization', 'User', 'MembershipLevel', 'OrganizationRole'); OrganizationPermission Model $belongsTo = array('OrganizationRole'); User Model $hasMany = array('Organization', 'MemberRelationship', 'Address'); So, as you can see, everything is related to Organization either directly or indirectly. So, I am thinking of adding actions to OrganizationsController to do things like viewMembers, editMembers, deleteMembers, viewRoles, editRoles, assignRoles, etc rather than putting calling view, edit, delete actions in MemberRelationshipsController and OrganizationRolesControllers. Any thoughts? Opinions? Suggestions? Thanks, Bill |
|
I think there are no hard and fast rules for this. I've done that in
the past where it seems to make sense to list the associated model data from a particular controller. If all you want to do is list the Members of a given Organization -- and not provide links to do anything further with a given Member -- then it might be fine to put the action in OrganizationsController. However, I'll generally create a controller for the other model(s), if only for admin functions. In your case, you may have a need for an admin to create a new OrganizationRole, for example. On Sun, Apr 22, 2012 at 12:45 PM, bs28723 <[hidden email]> wrote: > My question is - Is it a better MVC architecture to have a 1 to 1 > relationship for a controller to access the model and the view, or since > in a case where all relationships stem from a single model - just make > the one controller have all the actions, but pull data from the related > models needed together to then send to a view. > > Here is some code to help illustrate what I am talking about. ( I > removed a lot of configuration details, because it is not relevant for > the architecture discussion) > > Organization Model > $hasMany = array('OrganizationRole', 'Address', 'MemberRelationship'); > $belongsTo = array('User'); > > OrganizationRole Model > $hasMany = array('OrganizationPermission', 'MemberRelationship'); > $belongsTo = array('Organization'); > > MemberRelationship Model > $belongsTo = array('Organization', 'User', 'MembershipLevel', > 'OrganizationRole'); > > OrganizationPermission Model > $belongsTo = array('OrganizationRole'); > > User Model > $hasMany = array('Organization', 'MemberRelationship', 'Address'); > > > So, as you can see, everything is related to Organization either > directly or indirectly. So, I am thinking of adding actions to > OrganizationsController to do things like viewMembers, editMembers, > deleteMembers, viewRoles, editRoles, assignRoles, etc > rather than putting calling view, edit, delete actions in > MemberRelationshipsController and OrganizationRolesControllers. > > Any thoughts? Opinions? Suggestions? > > Thanks, > Bill > > ________________________________ > View this message in context: Understanding MVC Architecture > Sent from the CakePHP mailing list archive at Nabble.com. > > -- > Our newest site for the community: CakePHP Video Tutorials > http://tv.cakephp.org > Check out the new CakePHP Questions site http://ask.cakephp.org and help > others with their CakePHP related questions. > > > To unsubscribe from this group, send email to > [hidden email] For more options, visit this group at > http://groups.google.com/group/cake-php -- Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions. To unsubscribe from this group, send email to [hidden email] For more options, visit this group at http://groups.google.com/group/cake-php |
|
Thanks for the reply. It just seems like I am putting 100 functions
in the one controller and a 100 views in the one folder. Just
managing the code and the single file could get complicated.
But from a user experience, they are managing the organization. These are just areas to manage. So, maybe my question should be... What is a better way to manage the code? Maybe I should create components to manage the code related to a Model? On 4/24/2012 3:08 PM, lowpass [via CakePHP] wrote: I think there are no hard and fast rules for this. I've done that in |
|
On Tue, Apr 24, 2012 at 8:12 PM, bs28723
<[hidden email]> wrote: > Thanks for the reply. It just seems like I am putting 100 functions in the > one controller and a 100 views in the one folder. Just managing the code and > the single file could get complicated. Then you should probably be breaking things up a bit. Also, keep in mind that it's always better to put as much code into your models rather than the controllers. You can always call its methods by $this->Model1->Model2->doSomething() if they're associated. > But from a user experience, they are managing the organization. These are > just areas to manage. Yet in some case, you'll be managing a specific Member. There shouldn't really be any need to do so from the OrganizationsController. For listing all of the Members within an Org, sure. But then to edit one of them, you can go to the MembersController. Once saved, redirect back to the OrganizationsController. Router::connect( '/admin/orgs/:id', array( 'admin' => 1, 'controller' => 'organizations', 'action' => 'view' ), array('id' => '[0-9]+', 'pass' => array('id')) ); public function admin_view($id = null) { // pull data for some org } Router::connect( '/admin/orgs/:id/members', array( 'admin' => 1, 'controller' => 'organizations', 'action' => 'members' ), array('id' => '[0-9]+', 'pass' => array('id')) ); public function admin_members($id = null) { // pull data for some org and list members } When you list the members, create a link pointing to the MembersController: foreach($data['Member'] as $member) { $this->Html->link( $member['name'], array( 'admin' => 1, 'controller' => 'members', 'action' => 'edit', 'id' => $member['id'] ), array('title' => 'edit this member') ); } Router::connect( '/admin/members/edit/:id', array( 'admin' => 1, 'controller' => 'members', 'action' => 'edit' ), array('id' => '[0-9]+', 'pass' => array('id')) ); public function admin_edit($id = null) { // validate and save ... // redirect back to org's member list $route = array( 'admin' => 1, 'controller' => 'organizations', 'action' => 'members', 'id' => $this->request->data['Member']['organization_id'] ); $this->redirect($route); } > So, maybe my question should be... > > What is a better way to manage the code? Maybe I should create components > to manage the code related to a Model? No, don't do that. If you start creating components to handle model-specific tasks then you'd definitely be going in the wrong direction. Also, it's difficult to tell by just seeing the model names and not the entire schema, but my hunch is that you might be able to normalize things so that you have fewer models overall. But that really depends on what exactly you need to do. -- Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions. To unsubscribe from this group, send email to [hidden email] For more options, visit this group at http://groups.google.com/group/cake-php |
|
Great ideas. I will see about pushing more into the models. I have not
really done much with the router, but that gives me some ideas on how I can do some things. The data is fairly normalized, I am sure there is room for improvement. But it needs to scale. Basic premise is Users manage their profile, and can do a few things. Users can create organizations. The User/Owner of the Organization can manage it. Users can join Organizations. Users can join multiple organizations and have different roles. If you are familiar with facebook groups then this concept is part of my site. I an not trying to recreate facebook or anything like that, but some of the features of signup, moderation or manage the group, are a good analogy. The main point is that it has to scale and that there are several many to many tables. Which brings up another question - I had some challenges getting the multiple roles and ACL working. So, I have basically used Controller based authorization and isAuthorized routines. This works well. The documentation talks about you could go to a model based authorization. I assume it works the same, except that the isAuthorized routines will be in the Models instead of the controllers. I can't seem to find a lot of examples of why to do this? I don't know if this would be a good idea or not. Do you have any ideas or thoughts about this? Thanks again for the help. |
|
In reply to this post by lowpass
Just to make sure I understand what you said about putting code into the
models.... For the most part, anything that verifies, modifies, reads data from the DB should be in the model. The controller, just collects data, directs the models to read/change/update the data, then send to the view for presentation. so this would be a good controller function ... function viewMembers($orgId) { $this->Organization->id = $orgId; $this->set('user', $this->Auth->user()); if (!$this->Organization->exists()) { throw new NotFoundException(__('Invalid organization')); } $this->set('organization', $this->Organization->read(null, $orgId)); if (!isset($this->MemberRelationship)) $this->loadModel('MemberRelationship'); $this->MemberRelationship->recursive = 0; $this->set('memberRelationships', $this->paginate('MemberRelationship', array('MemberRelationship.organization_id' => $orgId))); $this->set('perms', $this->perms); } And this would be a good example of a controller functions that needs to have the part setting default values in request->data moved to a model function. Right? public function add() { $user = $this->Auth->user(); if ($this->request->is('post')) { // ****** move following to a Model Function *********** $this->request->data['Organization']['active'] = true; // default value $this->request->data['Organization']['valid_until'] = date('Y-m-d h:i:s', strtotime('+1 week')); // default value $this->request->data['OrgShipAddress']['first_name'] = $user['first_name']; // set default value from user $this->request->data['OrgShipAddress']['middle_name'] = $user['middle_name']; // set default value from user $this->request->data['OrgShipAddress']['last_name'] = $user['last_name']; // set default value from user $this->request->data['OrgShipAddress']['company'] = $this->data['Organization']['name']; // set default value from user $this->request->data['Organization']['contact_user_id'] = $user['id']; // set default value from user $this->request->data['Organization']['alt_contact_user_id'] = $user['id']; // set default value from user $this->request->data['OrgShipAddress']['user_id'] = $user['id']; // set default value from user if ( $this->request->data['Organization']['BillingSame']) { // use same address for billing unset($this->request->data['OrgBillAddress']); $this->request->data['OrgShipAddress']['user_id'] = $user['id']; // set default value from user } else { $this->request->data['OrgBillAddress']['first_name'] = $user['first_name']; // set default value from user $this->request->data['OrgBillAddress']['middle_name'] = $user['middle_name']; // set default value from user $this->request->data['OrgBillAddress']['last_name'] = $user['last_name']; // set default value from user $this->request->data['OrgBillAddress']['company'] = $this->data['Organization']['name']; // set default value from user $this->request->data['OrgBillAddress']['user_id'] = $user['id']; // set default value from user } // ********* above should be done by a Model Function ******* $this->Organization->create(); if ($ret = $this->Organization->saveAssociated($this->request->data)) { if ( $this->request->data['Organization']['BillingSame']) { $result = $this->Organization->saveField('bill_address_id',$this->Organization->OrgShipAddress->id); } else { $result3 = $this->Organization->OrgBillAddress->saveField('organization_id',$this->Organization->id); } $result2 = $this->Organization->OrgShipAddress->saveField('organization_id',$this->Organization->id); $orgId = $this->Organization->getLastInsertId(); if (!isset($this->OrganizationRole)) $this->loadModel('OrganizationRole'); $ret = $this->OrganizationRole->createDefaultRoles($orgId); if ($ret == false) { $this->Session->setFlash(__('Default Org Roles not created.')); } else { $role = $this->OrganizationRole->find('first', array( 'fields' => array('OrganizationRole.id','OrganizationRole.name','OrganizationRole.active'), 'conditions' => array('OrganizationRole.organization_id' => $orgId, 'OrganizationRole.name' => 'owner'), 'recursive' => 0)); $ret = false; if ( isset($role['OrganizationRole']['id'])) { if (!isset($this->MemberRelationship)) $this->loadModel('MemberRelationship'); $ret = $this->MemberRelationship->addRelationship($user, $orgId, $role['OrganizationRole']['id']); } if ($ret) { $this->Session->setFlash(__('The organization has been saved')); } else { $this->Session->setFlash(__('The User / organization relationship could not be saved. Please, try again.')); } } $this->redirect(array('action' => 'view', $this->Organization->id)); } else { $this->Session->setFlash(__('The organization could not be saved. Please, try again.')); } } } |
| Powered by Nabble | Edit this page |
