20 notes &
Content-type mapping with Lithium
Recently I started experimenting with Lithium, an awesome PHP framework. I really like it’s style, as it uses many new features of PHP 5.3 which really can make your code a lot leaner.
I wanted to return JSON in some occasions and Lithium has a neat feature on collections where you can call ->to(‘json’) on an result set. It works out of the box, but there is a problem with the formatting of the JSON. It looks like this:
{"1":{"id":"1","family_id":"2","family_position":"0","na....},{"id":"2","fami....}}
As you see, it is an object with objects in it. The desired result in my case is an array of objects, like this:
[{"id":"1","family_id":"2","family_position":"0","na....},{"id":"2","fami....}]
I started looking around the interwebs to find a solution. But I didn’t find a satisfying answer in the Li3 manual, so I started to browse the API docs. The docs for the Media class, the class responsible for almost everything what has to do with content-types, gave me the answer right away.
Within the file config/bootstrap/media.php you can declare custom content-types and assign custom handlers. With that knowledge things got really easy. I knew that I could get the desired result if I manually altered the results in the controller, but that doesn’t really adhere to the DRY principle. Declaring my own handler for the JSON format was the solution.
Media::type('json', 'application/json', array(
'encode' => function($data) {
$result = array();
foreach($data as $object) {
$result[] = $object;
}
return json_encode($result);
}
));
This small snippet fixed my problem! I can now render JSON like this:
$this->render(array('json' => Projects::all()));
The cool thing about this feature is that it works for many more content-types, for instance csv, like in the example in the Li3 API docs.