Home Kate Rose Morley on Twitter

Creating CSV downloads in PHP

The comma-separated values (CSV) file format is the most widely supported means of representing tabular data. Including a CSV export feature in a web application allows its data to be processed by other applications, increasing its value to users.

Basic example

This code outputs a simple CSV file and offers it as a download:

1
2
3
4
5
6
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=users.csv');

$output = fopen('php://output', 'w');
fputcsv($output, ['ID', 'E-mail address',   'Name']);
fputcsv($output, ['1',  'kate@example.com', 'Kate Rose Morley']);

Lines 1 and 2 output HTTP headers declaring that the content is UTF-8-encoded CSV data and that the browser should offer to download it. The Content-Disposition header not only ensures the file is offered as a download rather than displayed in the browser, but also allows a file name to be suggested — users.csv in this example — rather than leaving the browser to create a file name based on the URL.

Line 4 creates a file pointer that can be used to write to the PHP output stream, and then lines 5 and 6 use the fputcsv function to output a row of headers and a row of data.

MySQL example

In this example, the list of users is exported from a MySQL database:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=users.csv');

$output = fopen('php://output', 'w');
fputcsv($output, ['ID', 'E-mail address', 'Name']);

$connection = new mysqli('host', 'user', 'password', 'database');
$rows = $connection->query(
  'SELECT user_id,email_address,name FROM users',
  MYSQLI_USE_RESULT
);
while ($row = $rows->fetch_row()) {
  fputcsv($output, $row);
}

Lines 7 to 11 query the database for the list of users. The MYSQLI_USE_RESULT flag avoids an extra copy of the data being held in memory, allowing larger CSV files to be exported. Lines 12 to 14 then output each row returned by the query.