I’m currently revamping the API of NoseRub to use CakePHP’s Router::parseExtensions() magic, i.e. if you append an extension like “.json” to the action you request, then CakePHP automagically sets the correct content type, and uses extension-specific layouts and views to render the result (e.g. if you request /example/action.json then the layout app/views/layouts/json/default.ctp and the view app/views/example/json/action.ctp are used by default).
That’s nice, however, in our case all JSON views are identical (the same applies for the XML views):
// requires the JSON part from the Zend framework
App::import('Vendor', 'json', array('file' => 'Zend'.DS.'Json.php'));
echo Zend_Json::encode(array('data' => $data));
And so following the default approach would lead to a lot of duplication and many unnecessary folders and view files. And that’s not that cool ;-)
After some experimentation I found a better way.
For each extension I created a folder with a default view:
app
views
json
default.ctp
xml
default.ctp
json/default.ctp contains the code I have shown above, and xml/default.ctp would look like:
echo $xml->serialize(array('data' => $data), array('format' => 'tags'));
To tell CakePHP it should render those default views when there is not a more specific view, I added the following beforeRender() callback method to the AppController:
// app/app_controller.php
class AppController extends Controller {
public function beforeRender() {
$pathToViewFile = dirname(__FILE__).DS.'views'.DS.$this->viewPath.DS.$this->action.'.ctp';
if (!file_exists($pathToViewFile)) {
$this->viewPath = $this->layoutPath;
$this->action = 'default';
}
}
}
Happy baking!

Nice one.
This technique looks very usable for most alternative extensions, at least most I use, are “data” formats.
There is VIEWS constant, but it will not help much in case of multiple view paths or usage from plugins anyway.
Also, changing $this->action might lead to some bugs hard to find, I would go for AppController::render() instead.
why Zend_Json::encode?
when cake has $javascript->object($data);
which uses PHP jason_encode if available.
Is there any known issues with php jason_encode?
Zend Jason class looks odd to me (recursion, Solar framework code for unicode, performance…).
@all: Thanks for your comments!
@poLK: Yes, overriding the render() method could be an alternative, though I wasn’t able to make this approach work…
@majna: No, there is no issue with PHP’s json_encode (Zend/Json also uses this function if available). And the reason we use Zend/Json over $javascript->object() is that it automatically encodes special characters.