Exporting Data to a Downloadable CSV File with CakePHP 3 and CsvView

A couple of years ago I wrote about Exporting Data to a Downloadable CSV File with CakePHP which is still getting a lot of interest; however, at the time it was pointed out that a better way of handling CSVs in Cake was using a View Class.

Now that CakePHP 3 is out I thought it would be a good idea to write an updated piece on exporting data to a CSV using the excellent CsvView plugin.

Using CsvView significantly simplifies generating the CSV, removing the chore of having to manually iterate over data, especially if needed for more than one export method. So the fist step is to install the plugin:-

$ composer require friendsofcake/cakephp-csvview:~3.0

Next we need to load the plugin in config/bootstrap.php:-

Plugin::load('CsvView');

As an example we’ll consider a Subscriber model that contains contact details of people who have subscribed to our app. We want to create a CSV export of all the subscribers’ data.

The Controller

Let’s start with the controller. We need to create an action in the Subscriber’s Controller for generating the CSV export:-

<?php
// src/Controller/SubscribersController.php
class SubscribersController extends AppController {
	public function export() {
		$this->response->download('export.csv');
		$data = $this->Subscriber->find('all')->toArray();
		$_serialize = 'data';
   		$this->set(compact('data', '_serialize'));
		$this->viewBuilder()->className('CsvView.Csv');
		return;
	}
}

Let’s run through what this code is doing. Firstly we’re setting the relevant headers so that the browser will know to download the file:-

$this->response->download('export.csv');

When you trigger the controller’s action from the browser it will start to download a file named export.csv rather than attempt to display the view in the browser.

Next we grab the data from the database and set it ready for the View (the $data array):-

$data = $this->Subscriber->find('all')->toArray();
$_serialize = 'data';
$this->set(compact('data', '_serialize'));

It’s important to also set the $_serialize variable so that the View class will know which variables to use for rendering the CSV; this is the same as how Cake’s JsonView and XmlView work if you’re familiar with them.

Finally we tell Cake to use the Csv View class provided by the plugin:-

$this->viewBuilder()->className('CsvView.Csv')

This will handle the rendering of our data without the need for creating a View template and having to handle the content ourselves.

Setting a Header Row

So far our CSV file is a simple output of all our subscribers’ data, it would be useful to include a header row at the top of our file. With CsvView we can do that by setting $_header:-

$_header = ['ID', 'Name', 'Email'];
$this->set(compact('data', '_serialize', '_header'));

If you need a footer row you can do much the same as the header using $_footer.

Restricting Columns Included in the CSV

There will be times where we also only want to include specific columns from our find() in our CSV file. We can do this using $_extract like this:-

$_extract = ['id', 'name', 'email_address'];
$this->set(compact('data', '_serialize', '_header', '_extract'));

The Csv View class is very powerful and you can do a lot more with it than shown here. Check out the plugin’s documentation for full details.

The Route

As it currently stands the URL for our CSV export will be ‘subscribers/export’; it would be nice to append that with the CSV extension. To do that we’re going to tell Cake to correctly parse CSV file requests. In our config/routes.php file add the following:-

Router::extensions(['csv']);

This will now allow us to access our CSV export from the URL ‘subscribers/export.csv’.

Finally

Everything should now be setup, we just want to be able to link to our CSV export from a View. If you’re parsing the file extension then you need to include this in the URL; so using the HtmlHelper we need to include the ‘_ext’ parameter for the file extension:-

<?= $this->Html->link('export', [
	'controller' => 'subscribers', 
	'action' => 'export',
	'_ext' => 'csv'
]) ?>

That should be it! Clicking on the ‘export’ link should start the browser downloading our export.csv file.

Related Content

Published on


Comments

  1. Shain |

    Can I export an image into a csv file using this plugin?

  2. Andy |

    Hi Shain, CSVs are just plain text files so you can’t exactly embed an image into the file.

  3. Sivaram |

    Hi,
    After composing i am getting this error…

    Installation failed, reverting ./composer.json to its original content.

    [ErrorException] Undefined variable: baseDir

    Can you please help me.?
    Thank You in advance,

  4. Sid |

    hi and thank you for your post !

    unfortunely, I have this error :

    The action export.csv is not defined in ConferencesController
    Error: Create ConferencesController::export.csv() in file: src/Controller/ConferencesController.php.

    Can you help me ?

  5. Sébastien |

    Hi Andy,

    Thanks for your job.
    How do I load another view simultaneously export ?

  6. Tiago |

    Thanks for the post, help me a lot.

  7. James |

    How i set the format of the 1 column with this plugin?

  8. Rosa Rojas |

    Thanks for the tutorial super intelligible worked perfect

Leave a Comment
  • You will need to preview your comment before you can submit it.