The easiest would be to get your data together in a unified format (if it isn't already) and pass it to a method in your base controller to handle that logic in pretty much the same way you showed in your example.
abstract class AbstractController extends \Phalcon\Mvc\Controller
{
protected function prepareResponse($data)
{
// JSON is identified
if ($this->request->getBestAccept() == 'application/json')
{
// JSON rendering (case 3)
$this->response->setContentType('application/json');
$this->response->setJsonContent($data);
$this->view->disable();
return $this->response;
}
// Otherwise, defaults to HTML
// Passing data to the view
$this->view->setVars($data);
// Ajax call is identified
if ($this->request->isAjax())
{
// Partial rendering (case 2)
$view->disableLevel(array(
View::LEVEL_LAYOUT => true,
View::LEVEL_MAIN_LAYOUT => true
));
}
// Defaults to normal rendering
else
{
// Layout rendering (case 1)
}
return null;
}
}
class ProductsController extends AbstractController
{
public function indexAction()
{
// Build data and prepare response
return this->prepareResponse(array(
'products' => Products::find(array(
'foo' => $this->request->get('foo')
))
));
}
}
Otherwise, it might be a bit tricky. I see the following alternative scenarios.
Extend your base controller with, say, renderJson
and renderPartial
methods, to handle those bits of logic (default otherwise), but in your action you still would need to check which one to call. Duplication…
Do some crazy shit with the router to go to different action, e.g., indexJsonAction
and indexPartialAction
(default otherwise), depending on the conditions. But you'd end up with bloated controllers.