Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AndreiTelteu/790ab55e6e0d555ff247a0bd1d456676 to your computer and use it in GitHub Desktop.
Save AndreiTelteu/790ab55e6e0d555ff247a0bd1d456676 to your computer and use it in GitHub Desktop.
Export operation for backpack admin panel, that exports the entire database table, not just the entries shown on page
  1. First install maatwebsite/excel package:
composer require maatwebsite/excel
  1. Copy export.blade.php from this gist in resources/views/vendor/backpack/crud/buttons/export.blade.php

  2. Copy ExportOperation.php from this gist in app/Traits/Operations/ExportOperation.php

  3. Add the operation to your Crud controller

<?php

namespace App\Http\Controllers\Admin;
...
class UsersCrudController extends CrudController
{
    ...
    use \App\Traits\Operations\ExportOperation; // add this line to activate the operation
}
  1. DONE 😁 the export button should appear

Complete example with all the available customizations:

<?php

namespace App\Http\Controllers\Admin;
...
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate; // add this only if you want to use an excel date format

class UsersCrudController extends CrudController
{
    use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
    use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
    use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
    use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
    use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
    use \App\Traits\Operations\ExportOperation; // add this line to activate the operation
    
    protected function setupListOperation()
    {
        CRUD::column('image');
        CRUD::column('name');
        CRUD::column('email')->label('Email Address');
        // by default the export uses the same columns that are defined in the list operation
        // the header row in the final export uses the label attribute
    }
    
    public function getExportExtraColumns()
    {
        // with this function you can remove or add new columns in the final export file
        CRUD::column('image')->remove();
        CRUD::column('id')->makeFirst();
        CRUD::column('created_at');
    }
    
    public function getExportMapping($entries, $type): array {
        // with this function you can customize the data processing and format
        return $entries->map(function ($item) use ($type) {
            $data = $item->only(['id', 'name', 'email']);
            
            // this is how to make a column type date only in the excel export
            $data['created_at'] = $type == 'excel' ? ExcelDate::dateTimeToExcel($item->created_at->format('Y-m-d'))
                : $item->created_at->format('Y-m-d');
            
            return $data;
        })->toArray();
    }
    
    public function getExportFormat(): array {
        // for a date column in excel you also need this function
        // find other formats here: https://github.com/PHPOffice/PhpSpreadsheet/blob/master/src/PhpSpreadsheet/Style/NumberFormat.php
        return [
            'B' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDD,
        ];
    }
    
    // you can also extend this with another format if you need
    public function getExportTypes(): array
    {
        return [
            // defaults
            'csv' => 'CSV',
            'excel' => 'Excel',
            // custom
            'pdf' => 'PDF',
        ];
    }
    public function exportAsPdf($data)
    {
        // $data['entries']
        // $data['columns']
        // $data['filename']
        // you must return the file for view, or with some headers for download.
    }
    
    // with this function you can customize the filename
    public function getExportFilename(): string
    {
        // by default it does something like: Export-Users-2022-05-25
        return 'All users '.date('Y-m-d H:m');
    }
    
    
    
}
@if ($crud->hasAccess('export'))
<!-- export button group -->
<div class="btn-group">
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" tabindex="2">
<i class="la la-download"></i> {{ trans('backpack::crud.export.export') }}
</a>
<ul class="dropdown-menu dropdown-menu-right">
<li class="dropdown-header">Export as:</li>
@foreach ($crud->get('export.exportTypes') as $key => $type)
<a class="dropdown-item" href="{{ url($crud->route.'/export') }}?type={{ $key }}">{{ $type }}</a>
@endforeach
</ul>
</div>
@endif
<?php
namespace App\Traits\Operations;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
trait ExportOperation
{
/**
* Define which routes are needed for this operation.
*
* @param string $name Name of the current entity (singular). Used as first URL segment.
* @param string $routeName Prefix of the route name.
* @param string $controller Name of the current CrudController.
*/
protected function setupExportRoutes($segment, $routeName, $controller)
{
Route::get($segment.'/export', [
'as' => $routeName.'.export',
'uses' => $controller.'@export',
'operation' => 'export',
]);
}
/**
* Add the default settings, buttons, etc that this operation needs.
*/
protected function setupExportDefaults()
{
$this->crud->allowAccess('export');
$this->crud->operation(['list', 'export'], function () {
$this->crud->loadDefaultOperationSettingsFromConfig();
$this->crud->set('export.exportTypes', $this->getExportTypes());
$this->crud->addButton('top', 'export', 'view', 'crud::buttons.export', 'end');
});
}
/**
* You can define additional export columns here.
*/
public function getExportExtraColumns()
{
}
/**
* Get the types of supported export formats.
*
* @return array Array with export types and labels for the frontend button
*/
public function getExportTypes(): array
{
return [
'csv' => 'CSV',
'excel' => 'Excel',
];
}
/**
* You can customize the mapping of the export columns.
*
* @param array $entries Array entries
* @param string $type Type of export file
* @return array
*/
public function getExportMapping($entries, $type): array
{
return $entries->toArray();
}
/**
* You can customize the format of exported columns.
* https://docs.laravel-excel.com/3.0/exports/column-formatting.html
*
* @return array
*/
public function getExportFormat(): array
{
return [];
}
/**
* Get the export filename.
*
* @return string $filename
*/
public function getExportFilename(): string
{
$title = $this->crud->getTitle() ?? $this->crud->entity_name;
return 'Export-'.ucfirst($title).'-'.date('Y-m-d');
}
/**
* Generate the export based on request file-type.
*
* @return \Illuminate\Http\Response
*/
public function export()
{
$this->crud->hasAccessOrFail('export');
$this->setupListOperation();
$this->getExportExtraColumns();
$types = $this->crud->get('export.exportTypes');
$columns = $this->crud->columns();
$filename = $this->getExportFilename();
$type = request()->get('type');
if (!$type || !in_array($type, array_keys($types))) {
abort(500, 'Invalid export type');
}
$exportMethodName = 'exportAs'.Str::studly($type);
if (!method_exists($this, $exportMethodName)) {
abort(500, 'Export type is not supported');
}
$entries = $this->crud->getEntries();
$entries = $this->getExportMapping($entries, $type);
$format = $this->getExportFormat();
$title = $this->crud->getTitle() ?? $this->crud->entity_name;
$data = [
'title' => ucfirst($title),
'filename' => $filename,
'columns' => $columns,
'entries' => $entries,
'format' => $format,
];
$result = $this->{$exportMethodName}($data);
return $result;
}
/**
* Export as csv file
*
* @param array $data Array with title, filename, columns, entries
* @return \Illuminate\Http\Response
*/
public function exportAsCsv($data)
{
$callback = function () use ($data) {
$columns = collect($data['columns']);
$file = fopen('php://output', 'w');
// Add headers
fputcsv($file, $columns->pluck('label')->toArray());
// Add rows
foreach ($data['entries'] as $item) {
fputcsv($file, $columns->map(function ($column) use ($item) {
return $item[$column['name']];
})->toArray());
}
fclose($file);
};
$headers = [
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename={$data['filename']}.csv",
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
];
return response()->stream($callback, 200, $headers);
}
/**
* Export as excel file
*
* @param array $data Array with title, filename, columns, entries
* @return \Illuminate\Http\Response
*/
public function exportAsExcel($data)
{
$collection = collect($data['entries']);
$columns = collect($data['columns']);
$format = $data['format'];
$export = new class($collection, $columns, $format) implements
\Maatwebsite\Excel\Concerns\FromArray,
\Maatwebsite\Excel\Concerns\WithHeadings,
\Maatwebsite\Excel\Concerns\ShouldAutoSize,
\Maatwebsite\Excel\Concerns\WithColumnFormatting,
\Maatwebsite\Excel\Concerns\WithMapping
{
use \Maatwebsite\Excel\Concerns\Exportable;
private $collection;
private $columns;
private $format;
public function __construct($collection, $columns, $format) {
$this->collection = $collection->toBase();
$this->columns = $columns;
$this->format = $format;
}
public function array(): array {
$columns = $this->columns;
return $this->collection->map(function ($item) use ($columns) {
return $columns->map(function ($column) use ($item) {
return $item[$column['name']];
})->toArray();
})->toArray();
}
public function map($item): array {
return array_values($item);
}
public function columnFormats(): array {
return $this->format;
}
public function headings(): array {
return $this->columns->pluck('label')->toArray();
}
};
return $export->download(
$data['filename'].'.xlsx',
\Maatwebsite\Excel\Excel::XLSX
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment