Sling Academy
Home/PHP/How to return a CSV file in Laravel

How to return a CSV file in Laravel

Last updated: January 16, 2024

Introduction

When it comes to generating downloadable content, CSV files are one of the most common formats developers come across. In Laravel, creating and downloading such files can be accomplished effortlessly. This tutorial will guide you through the process of creating and serving CSV files in a Laravel application using various techniques and packages.

Prerequisites

  • Basic knowledge of PHP and Laravel
  • A working Laravel application setup
  • Composer installed locally

Returning a Basic CSV File

Let’s start with the most basic implementation of returning a CSV file in Laravel using native PHP functions:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ExportController extends Controller
{
    public function downloadCSV()
    {
        $callback = function() {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, ['Header1', 'Header2', 'Header3']);
            fputcsv($handle, ['Data1', 'Data2', 'Data3']);
            fclose($handle);
        };

        return new StreamedResponse($callback, 200, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="export.csv"',
        ]);
    }
}

In the above code, a simple CSV file is created on the fly and sent to the browser as a download. The php://output is used to write the output directly as a streamed response.

Using Laravel’s Response Helpers

Laravel offers a more fluent interface for sending different types of responses, including CSV files. Let’s use the response helper to clean up our CSV output:

public function downloadCSV()
{
    $filename = "export.csv";
    $headers = [
        'Content-type' => 'text/csv',
        'Content-Disposition' => "attachment; filename=$filename",
        'Pragma' => 'no-cache',
        'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
        'Expires' => '0'
    ];

    $columns = ['Header1', 'Header2', 'Header3'];

    $callback = function() use ($columns) {
        $file = fopen('php://output', 'w');
        fputcsv($file, $columns);

        // Sample data
        foreach(range(1, 10) as $index) {
            fputcsv($file, ["Row $index Col 1", "Row $index Col 2", "Row $index Col 3"]);
        }
        fclose($file);
    };

    return response()->stream($callback, 200, $headers);
}

The code shows creating a CSV file with an array of headers and a loop to generate sample data. A cleaner approach to sending the CSV as a stream is demonstrated with the response helper.

Using A Predefined Array

Often, you need to export an existing array to CSV. Here’s how that can be achieved:

public function exportPredefinedArray()
{
    $list = [
        ['Header1', 'Header2', 'Header3'],
        ['Data1', 'Data2', 'Data3'],
        // Other data rows...
    ];

    $headers = [
        'Content-Type' => 'text/csv',
        'Content-Disposition' => 'attachment; filename="export.csv"',
    ];

    $callback = function() use ($list) {
        $file = fopen('php://output', 'w');
        foreach ($list as $row) {
            fputcsv($file, $row);
        }
        fclose($file);
    };

    return response()->stream($callback, 200, $headers);
}

This time, the data to be exported to CSV comes from a predefined array. We iterate over this array and output each row as a CSV line.

Generating CSV From Database

To export data from a database, you can fetch your models and loop through the results. For example, let’s export users:

use App\Models\User;

//...

public function exportUsers()
{
    $headers = [
        'Content-Type' => 'text/csv',
        'Content-Disposition' => 'attachment; filename="users.csv"',
    ];

    $callback = function() {
        $users = User::all();
        $csv = fopen('php://output', 'w');

        fputcsv($csv, ['ID', 'Name', 'Email']);

        foreach ($users as $user) {
            fputcsv($csv, [$user->id, $user->name, $user->email]);
        }

        fclose($csv);
    };

    return response()->stream($callback, 200, $headers);
}

This code retrieves all users from the User model and writes each user as a row in the CSV file.

Using Third-Party Libraries

While native solutions work great, third-party libraries can simplify the process. The laravel-excel package by Maatwebsite is a popular choice. First, install it:

composer require maatwebsite/excel

Then, use it to create an export class:

php artisan make:export UsersExport --model=User

Define the export format:

namespace App\Exports;

use Maatwebsite\Excel\Concerns\FromCollection;
use App\Models\User;

class UsersExport implements FromCollection
{
    public function collection()
    {
        return User::all();
    }
}

And finally, use it within a controller:

use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;

//...

public function exportExcel()
{
    return Excel::download(new UsersExport, 'users.xlsx');
}

This code snippet does not return a CSV format but an XLSX file, which is beneficial when working with Excel.

Advanced Usage – Customizing Exports

With laravel-excel, you can also customize the exported data:

public function map($user): array
{
    return [
        $user->id,
        $user->name,
        $user->email,
        $user->created_at->format('Y-m-d'),
    ];
}

public function headings(): array
{
    return [
        'ID',
        'Name',
        'Email',
        'Registered At',
    ];
}

The map method allows you to modify how each user is represented in the export, and the headings method customizes the headers.

Conclusion

In this tutorial, you’ve learned several ways to generate and return CSV files in Laravel. Whether you choose simple streaming techniques or powerful external packages, Laravel makes the process straightforward and efficient.

Next Article: How to create an XML sitemap in Laravel

Previous Article: How to return JSON response in Laravel

Series: Laravel & Eloquent Tutorials

PHP

You May Also Like

  • Pandas DataFrame.value_counts() method: Explained with examples
  • Constructor Property Promotion in PHP: Tutorial & Examples
  • Understanding mixed types in PHP (5 examples)
  • Union Types in PHP: A practical guide (5 examples)
  • PHP: How to implement type checking in a function (PHP 8+)
  • Symfony + Doctrine: Implementing cursor-based pagination
  • Laravel + Eloquent: How to Group Data by Multiple Columns
  • PHP: How to convert CSV data to HTML tables
  • Using ‘never’ return type in PHP (PHP 8.1+)
  • Nullable (Optional) Types in PHP: A practical guide (5 examples)
  • Explore Attributes (Annotations) in Modern PHP (5 examples)
  • An introduction to WeakMap in PHP (6 examples)
  • Type Declarations for Class Properties in PHP (5 examples)
  • Static Return Type in PHP: Explained with examples
  • PHP: Using DocBlock comments to annotate variables
  • PHP: How to ping a server/website and get the response time
  • PHP: 3 Ways to Get City/Country from IP Address
  • PHP: How to find the mode(s) of an array (4 examples)
  • PHP: Calculate standard deviation & variance of an array