Implementing a Comma Separated Values (CSV) "webservice"
A simple howto for beginners (by a beginner!) on rendering CSV output in a consistent manner with XML, RSS etc.
I started with CakePHP a few weeks ago and have had great success redeveloping an intranet web application. One of the strong draws to Cake was the promise of "free" webservice provision which is very important. We have a number of other applications that tap into the data feeds from this app. They vary in their requirements and complexity but generally the newer ones are looking for XML, and the older ones for CSV. There is also a small early dependance on RSS feeds internally for the data. So the default webservice covers 2 of those bases - fantastic!
I asked the question on the google group and received some varying responses, some criticising the idea that CSV should be called a webservice. I would agree that CSV clearly is not a webservice, but it seems strange not to treat it in the same way as it lends itself to the approach very well. After XML and RSS are just text rendered with tags, so why not text rendered with commas? :-) I have to do this on several similar models.
The requirement is largely the same as enabling the XML and RSS services, with the addition of the critical addition to routes.php
In summary what I want to be able to publish and make available to the consumers of my data is something like:
You should also be able to apply this methodology to other data outputs as well. Internally we have some of our own plain text layouts that are automatically sourced via wget and emailed that we will probably do in this manner as well.
What follows therefore is a brief and simplified primer of how I chose to implement this, which you should be able to extend for your own purposes. I'd be delighted to hear feedback as to whether this is the most appropriate method or not.
Edit your app/config/routes.php to include the following new route:
Download code
for example: app/views/employees/csv/index.thtml
? there may be a clever way of querying the model to derive the CSV headers (and therefore the row data I suspect). I don't know what this is yet.
References:
- Google Group Thread: http://groups.google.com/group/cake-php/browse_thread/thread/ccd5d340b656fc0f/04b3fa72a0b4166b?#04b3fa72a0b4166b
- CakePHP Manual on Advanced Routing: http://manual.cakephp.org/chapter/configuration
I asked the question on the google group and received some varying responses, some criticising the idea that CSV should be called a webservice. I would agree that CSV clearly is not a webservice, but it seems strange not to treat it in the same way as it lends itself to the approach very well. After XML and RSS are just text rendered with tags, so why not text rendered with commas? :-) I have to do this on several similar models.
The requirement is largely the same as enabling the XML and RSS services, with the addition of the critical addition to routes.php
In summary what I want to be able to publish and make available to the consumers of my data is something like:
- /items/index
- /xml/items/index
- /rss/items/index
- /csv/items/index
You should also be able to apply this methodology to other data outputs as well. Internally we have some of our own plain text layouts that are automatically sourced via wget and emailed that we will probably do in this manner as well.
What follows therefore is a brief and simplified primer of how I chose to implement this, which you should be able to extend for your own purposes. I'd be delighted to hear feedback as to whether this is the most appropriate method or not.
1. Tell Cake to watch for the new CSV "webservice".
Edit your app/config/routes.php to include the following new route:
Download code
$Route->connect('/csv/:controller/:action/*', array('webservices' => 'Csv'));
2. Create a default component app/controllers/components/csv.php
Component Class:
Download code
<?php
<?php
class CsvComponent extends Object {
}
?>
?>
3. Create a default helper app/views/helpers/csv.php
Helper Class:
Download code
<?php
<?php
class CsvHelper extends Helper {
}
?>
?>
4. Create a default layout file app/views/layouts/csv/default.thtml
View Template:
Download code
<?php header('content-type: text/plain'); ?>
<?php echo $content_for_layout ?>
5. Finally, create the appropriate controller action associated views
for example: app/views/employees/csv/index.thtml
View Template:
Download code
"ID","employeeLogin","employeeName" (.... etc)
<?php foreach($employees as $e); ?>
"<?php echo $e['Employee']['id']?>","<?php echo $e['Employee']['employeeLogin']?>","<?php echo $e['Employee']['employeeName']?>"
<?php endforeach; ?>
Open Questions:
? there may be a clever way of querying the model to derive the CSV headers (and therefore the row data I suspect). I don't know what this is yet.
References:
- Google Group Thread: http://groups.google.com/group/cake-php/browse_thread/thread/ccd5d340b656fc0f/04b3fa72a0b4166b?#04b3fa72a0b4166b
- CakePHP Manual on Advanced Routing: http://manual.cakephp.org/chapter/configuration
Latest Comments