I need a controller in my Zend Framework project, which should handle only ajax requests.
My approach at the moment is to extend the Zend_Controller_Action:
I have done much the same as you, I have a controller specifically for handling ajax requests, however my solution is much simpler, I have use the init() function rather than preDispatch.
My init() function looks like this
class Ajax_Controller extends Zend_Controller_Action
{
public function init()
{
$this->_helper->layout()->disableLayout();
}
//the rest of the controller...
}
That's it! I have made no other changes from a standard controller.
I disable view rendering in the action if required as I found, in my case, I needed a view to render tables etc.. However, if you only ever return json data then your method of disabling view rendering in preDispatch() is perfectly valid.
If I need to return json I have a similar function to yours and I disable view rendering.
I have used this method on 4 seperate, but similar, projects now without any issues. Having said that my ajax calls are usually pretty simple, but I don't see any issues with this method.
If you are looking for a simple, clean ajax implementation, then this may be an option for you.
markus explained the most "Zend Like" way and his explanation is correct. But you see it as too much overhead because he missed to show you how much the "json context switch" is the best for your case.
Look how short it is :
//In your controller, activate json context for ANY called action in once
public function init(){
$action = $this->_getParam('action');
$this->_helper->getHelper('contextSwitch')
->addActionContext($action, 'json')
->initContext();
}
And thats all, you don't need any view scripts, all the variables you assign via $this->view
will be serialized into a JSON object.
Oh and you don't want to add the context in the urls? Ok, just activate it by default in your route
routes.ajax.route = '/ajax/:action/*'
routes.ajax.defaults.controller = ajax
routes.ajax.defaults.action = index
routes.ajax.defaults.format = json
The content need only be switched when you're actually calling an ajax action. I think the Zend way is a good way. It is very flexible and easy to implement. In most cases, different Controllers will have a need for a couple of ajax actions. I don't see the need or the advantage of a pure ajax controller.
Every controller can have something like this in the init():
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('some-toggle', 'html');
$ajaxContext->addActionContext('some-other-ajax-thing', 'json');
$ajaxContext->initContext();
The action looks like every other action. The view script has just one var like:
<?php echo $this->response; ?>
... and has to be called actionname.ajax.phtml.
Then, if you're pushing additional actions on your action stack, you need to do that only for non-ajax requests like so:
if (!$request->isXmlHttpRequest())
{
//push actions on stack
}
Additionally, you have to pass a format param along with the ajax post url like posturl/format/html
or posturl/format/json
.
You can simply use
$this->_helper->json($data);
wherever you like. It disables everything not needed, clears the response, encode data to json, sends the response and set propper headers as a bonus. This is the most "zend-way" there is I guess ;)