0

I don't know how to do this:

I have a CakePHP project that uses AdministratorsController and UsersController for different roles, etc.. but, a User can save a Message and a Administrator too! So, should I repeat the same function or what?

function saveMessage(){
    $this->autoRender = false;
    if (!$this->RequestHandler->isPost())
        $this->Session->setFlash('Error 78.', 'flash_custom_danger');
    else{   
        if(!$this->Message->save($this->request->data))
            $this->Session->setFlash('Error 985.', 'flash_custom_success');
        else
            $this->Session->setFlash('Success!', 'flash_custom_success');       

    }
    $this->redirect('/');
}
Juliano Lima
  • 709
  • 3
  • 10
  • 17
  • Move the access control and business logic out of your "controllers". – tereško Jan 21 '14 at 19:41
  • But how the Model should to setFlash and redirect and check if it is Post? is Controller's responsability, isn't it? – Juliano Lima Jan 21 '14 at 19:51
  • Controllers responsibility is actually to alter model layer's state based on user input. Since you are using CakePHP, you should focus on writing code in "CakePHP style" instead of trying to apply MVC architecture. Mainly because former has completely nothing to do with latter. – tereško Jan 21 '14 at 19:54
  • Got it, but I learned this way.. Tell me then, how should I do this? what should be in the controller and model? just forget the 'sharing' – Juliano Lima Jan 21 '14 at 19:58
  • In your situation, I would move this type of functionality to a separate class *(you can think of it as a "model" that does not extend `AppModel`, but instead uses other instances of it ... thought, since you have been using Cake, [model is not what you think](http://stackoverflow.com/a/5864000/727208))* .. lets call it "Messneger". And then both your admin and mortal-user would be using an instance o this Messenger. – tereško Jan 21 '14 at 20:02

2 Answers2

1

Move the function to app_controller, because both your controllers will extend from it.

In the app_controller:

function my_function($controller_specific_string = null){ 
    //stuff here common to both controllers
}

In the controller(s):

function my_function() { //extended function in both controllers
  // do controller specific stuff here...

  return parent::my_function('from_users_controller');
}
Charles Harmon
  • 380
  • 2
  • 10
  • Ok, and if I have some almost similar code? Like some 3 lines different.. should I to process the parameters? – Juliano Lima Jan 21 '14 at 19:40
  • That's what I've done with cake in the past with shared functions and will set in the before_filter() for each controller a variable like, $this->myModuleName and pass it to the function. Ideally, you can do this in an extended function as well let me edit my answer... – Charles Harmon Jan 21 '14 at 19:58
  • 1
    why would you want **ALL** controllers to have `saveMessage()` method ? – tereško Jan 21 '14 at 19:59
  • 'Cause a User belongs to a Role, and when he authenticates, is redirected to the respective controller's role to render the view, I think it's more organized, but I don't know if it's right. – Juliano Lima Jan 21 '14 at 20:03
1

Ok, just for this kind of case (normally I'd advice to put the functionality in the model or in AppController) I'd just create a parent class.

Let's call it GeneralUsers (to late for imagination)

class GeneralUsersController extends AppController {
    protected function _saveMessage(){
        $this->autoRender = false;
        if (!$this->RequestHandler->isPost())
            $this->Session->setFlash('Error 78.', 'flash_custom_danger');
        else{   
            if(!$this->Message->save($this->request->data))
                $this->Session->setFlash('Error 985.', 'flash_custom_success');
            else
                $this->Session->setFlash('Success!', 'flash_custom_success');       
        }
        $this->redirect('/');
    }
}

And let's have your UsersController and AdministratorsController extend from that one

class UsersController extends GeneralUsersController {
    public function myAction() {
        $this->_saveMessage();
    }
}
// and the Administrator controller one

That way the only controllers with those functions are users and administrators.

Now, if this was the case where a bunch of validations are made before saving and you want to avoid repeating those, I'd say to put that in the models. If every controller should have access to that function, then put it in the AppController. But since an "Administrator" is an "User" with more privileges (and you are not separating that functionality with the "admin_" prefix), then go with an extra parent class. Be careful with the functions though, don't let them be public unless you want those to be accessible by url.

Nunser
  • 4,512
  • 8
  • 25
  • 37
  • Thanks, but the administrator is completely different from user in the sense of privilege, just the Messages are the same function, and I need to be public, because when he is logged in, he only can access the `Administrators` or `Users` controller. – Juliano Lima Jan 21 '14 at 21:06
  • @JulianoLima the answer is still valid. A parent class doesn't alter any priviledges of users or administrators (that was just a comment on how I see things). And Administrators and users will still have access to all their actions, you just have to have `_saveMessage` protected (but still callable from any action inside users or administrators controller). Did you give it a try? – Nunser Jan 22 '14 at 12:29