Recently popular package Laravel-Excel released a new version 3.0, which was a pretty radical change from previous versions. I needed to do a simple Excel export and noticed that their documentation covers only export from Laravel Collections but not from some custom structure. So I will show you a "workaround".
First, this is how documentation describes the basic workflow:
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
class InvoicesExport implements FromCollection
{
public function collection()
{
return Invoice::all();
}
}
You need to create a separate class for export (similar how Laravel Notifications work) and you can define a collection to export.
There are also other ways to export the data:
From Eloquent query:
class InvoicesExport implements FromQuery
{
use Exportable;
public function query()
{
return Invoice::query();
}
}
Or, from View HTML table:
class InvoicesExport implements FromView
{
public function view(): View
{
return view('exports.invoices', [
'invoices' => Invoice::all()
]);
}
}
But still, the problem is that all examples are based on Eloquent. What if I need Excel from some custom structure like array?
Imagine that I have this array:
[
[
'name' => 'Povilas',
'surname' => 'Korop',
'email' => '[email protected]',
'twitter' => '@povilaskorop'
],
[
'name' => 'Taylor',
'surname' => 'Otwell',
'email' => '[email protected]',
'twitter' => '@taylorotwell'
]
]
How do I export that into Excel, so that keys would be columns, and values would be rows?
There are two ways.
Option 1. Turn your Array into a Collection and add Headings
This is how the Export class would look:
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithHeadings;
class CollectionExport implements FromCollection, WithHeadings
{
use Exportable;
public function collection()
{
return collect([
[
'name' => 'Povilas',
'surname' => 'Korop',
'email' => '[email protected]',
'twitter' => '@povilaskorop'
],
[
'name' => 'Taylor',
'surname' => 'Otwell',
'email' => '[email protected]',
'twitter' => '@taylorotwell'
]
]);
}
public function headings(): array
{
return [
'Name',
'Surname',
'Email',
'Twitter',
];
}
}
You need to implement collection() method by using Laravel's collect() method and passing array to it. Also, you need to implement headings() to add a header row.
Finally, in Controller you will have this row at the end of the method:
return Excel::download(new CollectionExport(), 'export.xlsx');
Then you would have this as downloaded result:

Option 2. Pass Array into View
Alternatively, you can build this resources/views/exports/xml.blade.php:
<table>
<thead>
<tr>
@foreach($data[0] as $key => $value)
<th>{{ ucfirst($key) }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach($data as $row)
<tr>
@foreach ($row as $value)
<td>{{ $value }}</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
And then have this in your Export class:
namespace App\Exports;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class BladeExport implements FromView
{
public function view(): View
{
return view('exports.xml', [
'data' => [
[
'name' => 'Povilas',
'surname' => 'Korop',
'email' => '[email protected]',
'twitter' => '@povilaskorop'
],
[
'name' => 'Taylor',
'surname' => 'Otwell',
'email' => '[email protected]',
'twitter' => '@taylorotwell'
]
]
]);
}
}
Controller stays the same, just different class name:
return Excel::download(new BladeExport(), 'export.xlsx');
Wait, but how to pass data into Export class?
Both of our examples have one flaw - the data is formed in the class itself. Actually, it shouldn't even know about the data, it should accept it as a parameter. But how do we do that, if view() or collection() methods have no parameters?
We will pass it through __construct() method into a private variable. You could call it a dependency injection, although there are much better examples of dependency injection, look it up on Google.
class BladeExport implements FromView
{
private $data;
public function __construct($data)
{
$this->data = $data;
}
public function view(): View
{
return view('exports.xml', [
'data' => $this->data
]);
}
}
So we're accepting $data as a parameter now. Then, in our Controller we can have this:
$data = [
[
'name' => 'Povilas',
'surname' => 'Korop',
'email' => '[email protected]',
'twitter' => '@povilaskorop'
],
[
'name' => 'Taylor',
'surname' => 'Otwell',
'email' => '[email protected]',
'twitter' => '@taylorotwell'
]
];
return Excel::download(new BladeExport($data), 'export.xlsx');
I hope that's helpful. Check out other examples in official documentation of the package.
No comments or questions yet...