Skip to content
markstory edited this page Nov 15, 2011 · 3 revisions

Problem

Currently CakePHP has features to offer content-type based responses through RequestHandler and view switching. However, error pages are always served as HTML. Handling error pages as alternate content types is left up to the developer.

Additionally, creating simple data views in JSON and XML is a difficult task. It requires either duplicating all your view files + layouts for each content type. Or using custom view classes. Xml and Json responses are common enough that they should be built-in.

Possible solution

Use the built-in content type detection features to switch error rendering to alternate content types. (JSON, and XML will be built-in). Instead of duplicating 10's of templates a thin View class for each content type could be used. The View class could take the view vars + an additional 'serialize' key. The 'serialize' key informs the view class about which variables should be part of the alternate response.

Datatype views

Both JSON and XML are datatype views. They both support a 'serialize' key, and the option to render a view + layout if data transformations are required.

Using the serialize key

When you just want a simple data export you can use the serialize key. This key indicates a view variable that should be serialized to create the response data. For example if your controller sets an array of posts, and when sending the json response you only want to send the $posts. You could do the following:

$this->set(array('posts' => $posts, 'serialize' => 'posts'));

Using a normal view

When you need to do some manipulation of data before creating the output, you can exclude the serialize key, and use a normal view + layout file.

// app/View/Posts/json/index.ctp
<?php
foreach ($posts as &$post) {
    unset($post['secret_field']); 
}
echo json_encode($posts);

If an application requires shared view logic, this could be accomplished with view extension. Since data views don't use layouts like normal views you could create common shared output using an extended view.

// app/View/Posts/json/index.ctp
<?php
$this->extend('../Layouts/json/common.ctp');

foreach ($posts as &$post) {
    unset($post['secret_field']);
}
$count = count($posts);

$this->set(array('count' => $count, 'items' => $posts));
?>
// app/View/Layouts/json/common.ctp
<?php
json_encode(compact('count', 'items'));
Clone this wiki locally