This question is a case in hand.

Let's imagine a website page that displays a filtered products list :

  1. If I request /products?foo=bar in my browser, I get a full page wrapped in a layout, the layout contains a header with a form allowing to change search criterias.

  2. If I change foo value to baz and submit the form, it reloads dynamically the results (with a jQuery $.load(), for example), calling /products?foo=baz in Ajax.

  3. If I enter the same criteria into my iPhone app, the app requests /products?foo=bar to the server, which replies with a json object.

All 3 calls refer to the same resource ("the products list", resource is intended as in REST resource), but all need different rendering.

  1. In the first case, I need a full HTML page (with layout)
  2. In the second case, I need a partial HTML page (without layout)
  3. In the third case, I need a plain json response

This rendering switch can be triggered by the headers X-Requested-With (with or without layout) and Accept (html/json).

In Phalcon, the given example could be implemented as :

class ProductsController extends \Phalcon\Mvc\Controller
{

    public function indexAction()
    {
        // Build data
        $products = Products::find(array(
            'foo' => $this->request->get('foo')
        ));

        // JSON is identified
        if ($this->request->getBestAccept() == 'application/json')
        {
            // JSON rendering (case 3)
            $this->response->setContentType('application/json');
            $this->response->setJsonContent($products);
            $this->view->disable();
            return $this->response;
        }
        // Otherwise, defaults to HTML
        else
        {
            // Passing data to the view
            $this->view->products = $products;

            // 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)
            }
        }
    }

}

How could I implement this mechanism application-wide, rather than duplicate this behavior in every single action ?

Originally posted at http://stackoverflow.com/questions/23291132/switch-rendering-according-to-headers-application-wide