We can create and download CSV files in Laravel. In this tutorial, we will develop an application to learn how to generate and download CSV files in Laravel without using any package.
We will create some dummy data in MySQL database using Laravel factory and display data in pages using Laravel pagination.
This is a simple application and it is useful as well. All you have to do is select the data in the controller and display them in an html table. To create a CSV file, create a controller function to write the data in a file using fputcsv()
function.
Watch YouTube Video
Create the Laravel project
Create the Laravel project using the below command. We have given the project name as lara_csv.
composer create-project --prefer-dist laravel/laravel lara_csv
Migration
Update database details in the .env
file. We will be using a MySQL database named 'lara_demo':
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lara_demo
DB_USERNAME=root
DB_PASSWORD=
We will create a new table called "applications". We will make some test data in this table using Laravel Factory. Create a migration file for this table using the below command:
php artisan make:model Application -m
The above command will create a migration file <yyyy_mm_dd_xxxxxx>_create_applications_table.php
in the database/migrations folder and the model "Application" will be created in the app/Models folder.
Update Laravel migration file
Update the above migration file as below:
public function up(): void
{
Schema::create('applications', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('address')->nullable();
$table->timestamps();
});
}
Run the migration to create the tables. Run the below artisan command from the project folder:
php artisan migrate
After running the migration see the structure of the 'applications' table.
Update Application model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Application extends Model
{
use HasFactory;
protected $fillable = ['name', 'email', 'address'];
}
Add some dummy data using Laravel Faker
We will create some dummy data in the "applications" table. Let us create a factory for the Application model as below:
php artisan make:factory ApplicationFactory --model=Application
Update Application Factory as below:
public function definition(): array
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'address' => $this->faker->address,
];
}
Update the run()
method of DatabaseSeeder.php
under database/seeders folder to call the factory we just created. We will create 100 rows in the table.
public function run(): void
{
\App\Models\Application::factory(100)->create();
}
Now, run the database seeder to create the rows:
php artisan db:seed
Below are 100 rows created in the "applications" table.
Laravel Controller
Let us first take a look at the home page that displays all the applications
It displays the list of applications with a download CSV button. We will create the controller using the artisan command as below:
php artisan make:controller ApplicationController
The controller will have two methods:
index()
method to display all the applications.generateCsv()
method for creating a CSV file with the data for all the applications.
index() method
This method selects all records from the Application model and loads the index view.
public function index()
{
$data = Application::latest()->paginate(10);
return view('index',compact('data'));
}
We have used Laravel pagination to display 10 rows per page.
generateCsv() method
public function generateCsv(request $request)
{
$data = Application::latest()->get();
$filename = "application.csv";
$handle = fopen($filename, 'w+');
fputcsv($handle, array(
'Name',
'Email',
'Address',
));
foreach($data as $row) {
fputcsv($handle, array( $row['name'],
$row['email'],
$row['address'],
));
}
fclose($handle);
$headers = array('Content-Type' => 'text/csv');
return response()->download($filename, 'application.csv', $headers);
}
Open a file using PHP fopen() function to write the application details. This file has an extension as csv. When a user clicks on the download CSV button, this method will be called and the "application.csv" file will be created in the public folder and downloaded in the user's computer. Note that the header with Content-Type as text/csv has to be sent with the response.
Routes
Route::get('/', [ApplicationController::class, 'index'])->name('application.index');
Route::get('/get-csv', [ApplicationController::class, 'generateCsv'])->name('download.csv');
Create the views
We have one view to display the applications.
We have the below files in the resources/views folder
We will have the header and master layouts
resources/views/layouts/header.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Laravel Generate CSV</title>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
<meta name="_token" content="{{ csrf_token() }}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" media="screen" href="{{ asset('css/style.css') }}" />
</head>
resources/views/layouts/master.blade.php
@include('layouts.header')
<body>
@yield('main-content')
</body>
</html>
resources/views/index.blade.php
@extends('layouts.master')
@section('main-content')
<h1>Laravel Generate CSV</h1>
<div class="container">
<div class="text-end">
<a href="{{ route('download.csv') }}" class="btn btn-primary">Download CSV</a>
</div>
<h4>List of Applications</h4>
<div class="table-responsive">
<table class="table table-striped table-bordered mt-5">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Address</th>
</tr>
</thead>
<tbody>
@forelse($data as $index => $row)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $row->name }}</td>
<td>{{ $row->email }}</td>
<td>{{ $row->address }}</td>
</tr>
@empty
<tr>
<td colspan="6">No Applications Found</td>
</tr>
@endforelse
</tbody>
</table>
{{ $data->links() }}
</div>
@endsection
Use the below stylesheet:
public/css/style.css
* {box-sizing: border-box;
}
body {
margin: 0;
font-family: Helvetica, sans-serif;
font-size:14px;
}
h1,h4{
text-align: center;
margin-bottom: 20px;
margin-top: 10px;
}
.container{
min-height: 600px;;
}
table>thead{
background-color:#2b5171;
color:#fff;
}
Test the application
Start the PHP development server using the artisan command:
php artisan serve
Run localhost:8000
in the browser. Verify if the application is working correctly. Test the below cases:
- List Applications with pagination.
- Download the CSV file and make sure all the rows appear in the CSV file.
Post a Comment