views:

87

answers:

3

I am using MVC in PHP based Zend Framework. This is more of a design question. I have a controller that has a couple of actions. These actions are accessed via AJAX from the controller's view. The controller's actions, perform Business logic by accessing data from functions inside a model, and construct or echo HTML. This HTML is spit back to view in the AJAX response. My understanding of controllers is they are not supposed to contain any HTML at all. But given the AJAX in the views, I feel I don't have a choice except to generate HTML on the fly in the controller. Is this a good design? How can I improve it?

+1  A: 

Always try to leave any presentational logic inside a view. I think a correct design approach for your application would be something like :

AjaxController.php :

public function AjaxAction() {
    //do some logic
    //set content to a variable
}

ajax.phtml :

<p><?php //display the content of the variable setted in the controller ?></p>

You can later edit the view or the action separately, perhaps even rehuse the view for some similar ajax generated content, etc. Always try to separate things this way, that is the way MVC pattern is designed to work with.

Leprosy
+2  A: 

First of all, the business logic should be in the Model, not the Controller.

Secondly, My ajax requests commonly have this sort of format:

if ($ajax = $this->getRequest()->isXMLHttpRequest()) {
  $this->_helper->layout->disableLayout();   
};

// then later - if its responding with json:

  if ($ajax)
  {
    $this->_helper->viewRenderer->setNoRender(true);     
    $this->getResponse()->setHeader('Content-Type', 'text/json'); 
    echo $this->view->json($some_return_values);
    return;
  }

Also - don't forget you can use $this->view->render('controller/action.phtml'); to capture a rendered phtml into a string to return via the controller. This will allow you to keep presentation in the view.

gnarf
+4  A: 

There are two action helpers for doing exactly this. you can re-use your actions for multiple contexts with the ajaxContext or contextSwitch action helpers. The context switch is generally the more useful in my experience, and it can even automatically serialize the data you assign to the view in your action for json responses so there is no need for a view script.

you initialise the context switch like this:

class MyController extends Zend_Controller_Action
{
    public function init()
    {
        $contextSwitch = $this->_helper->getHelper('contextSwitch');
        $contextSwitch->addActionContext('index', 'json')
                      ->initContext();
    }
    public function indexAction()
    {
        $this->view->items = My_Model::fetchAll();
    }
}

The above will add a context of json to the context switch, and when the action is called with the request parameter 'format' set, it will automatically serialize the content, in this case giving a json array of the items returned by My_Model::fetchAll();

The format parameter can either be passed in the url "/my/index/format/json" or with a get query "/my/index?format=json"

The real magic is that the context switch also sets the appropriate headers for the response type, such as content-type.

You can even specify your own contexts, and the headers to send. Read more about the context switch here

Bittarman