Basic CSV Output in Zend Framework 2

In today’s tutorial we look at a simple way of rendering CSV output in Zend Framework 2, using only a View Template and Controller Action. We see just how easy it is to generate content and send it to the browser, instead of rendering a standard .pthml template.


Today’s tutorial is a simple one. We’re going to look at a simple way of rendering CSV output in Zend Framework 2 using a combination of a View Template and Controller Action. We’re going to see just how easy it is to generate content and send it to the browser, instead of rendering a standard .pthml template.

Time Required: 20 Minutes

Difficulty: Basic

The Module Configuration

Ok, in the module config.php file update it with the following configuration:

'view_manager' => array(
    'template_map' => array(
        'download/download-csv' =>
            __DIR__ .

Here, we’ve provided an alias, &'download/download-csv&', to a template which we’re about to create in our module view directory. Nothing too complex, so we’ll skip on to the actual view template itself.

The View Template

In your module, create a new template, download-csv.phtml, in a new directory &'download&', in the view directory for your module. In our case, it will be &'/../view/application/download/&'. Then, open the file and add the following code, which we’ll work through.

if (count($results) > 0) {
    $fh = @fopen( 'php://output', 'w' );
    foreach ($results as $result) {
        fputcsv($fh, $result);

What we’ve done here is use fputcsv to convert each record in $results to a CSV row then use PHP streams to store the CSV data in an output buffer. Like thoughtful developers, when we’ve finished iterating, we close the file handle on the stream we opened at the start.

The Controller Action

Finally, here we have the definition of the controller action. Add it to the controller in your module. Then let’s work through what’s going on.

protected function csvAction($filename, $resultset)
    $view = new ViewModel();
         ->setVariable('results', $resultset)

    if (!empty($columnHeaders)) {

            'columnHeaders', $columnHeaders

    $output = $this->getServiceLocator()

    $response = $this->getResponse();

    $headers = $response->getHeaders();
    $headers->addHeaderLine('Content-Type', 'text/csv')

                sprintf("attachment; filename=\"%s\"", $filename)
            ->addHeaderLine('Accept-Ranges', 'bytes')
            ->addHeaderLine('Content-Length', strlen($output));


    return $response;

What we’ve done is to explicitly initialise a ViewModel object, instead of the implicit way, which normally occurs. Then, we’ve specified the template, and set $results as a template variable, followed by a call to ViewModel’s setTerminal method.

If you’re not familiar with this method, it changes the normal view rendering procedure. Normally the view model returned from a controller action would be injected into the layout view model. When setTerminal is called, the returned View Model replaces the layout view model.

It’s really handy for console output, modal dialogs and other situations where we just want the content at the action level and nothing else.

Note: If you’re familiar with Zend Framework 1, then you would have likely called the following two functions to achieve the same effect:


Then, we use the ServiceLocator to get direct access to the ViewRender object and retrieve the content of the rendered template directly into $output. Finally, we manipulate the headers which are sent to the browser to stipulate we’re sending a CSV file as a downloadable file.

The headers (with definition) are:

Content HeaderDefinition
Content-TypeIndicates the media type of the entity-body sent to the recipient
Content-DispositionA means for the origin server to suggest a default filename if the user requests that the content is saved to a file
Accept-RangesAllows the server to indicate its acceptance of range requests for a resource
Content-LengthIndicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient

After we’ve done this, we set the body of the response to be the CSV content which we generated in the view and return the response object. The net result of doing this, is that a HTML view won’t be rendered. Instead, a CSV file will be downloaded via the browser.


Today we’ve looked at a simple way to generate CSV output in our controller actions. It takes a really simple path, looking directly at the components involved, without any special wrapper or helper functionality.

We could have gone in a number of directions, including creating and registering a custom rendering strategy. But it’s important to understand what the fundamentals are first, before progressing further. In next week’s tutorial, I’ll be creating a custom render strategy for CSV files (along with including the code on the Malt Blue Github repository.

Has this helped expand the types of content your application can produce? Do you know of a module which already does this? Either way, tell me in the comments.

You might also be interested in...

    comments powered by Disqus


    Docker Essentials. Learn the four essential skills you need to build and deploy applications with Docker! Mezzio Essentials. Learn the fundamentals that you need, to begin building applications with the Mezzio framework today!

    Latest YouTube Video

    Learn how to write SQL queries in PhpStorm