前言
Dcat admin提供了Easy Excel匯出資料(預設未安裝),文件給出的例子為:
$grid->export()->rows(function (array $rows) {
foreach ($rows as $index => &$row) {
$row['name'] = $row['first_name'].' '.$row['last_name'];
}
return $rows;
});
很一目瞭然,也很簡單,但是假如遇到很複雜的資料處理,就顯得不夠優雅。因此需要把資料匯出提出來,做成單獨的元件,在控制器中引用就可以。例如定義了一個UserExporter,那麼在控制器中使用應該為:
$grid->export(new UserExporter());
在檢視了Easy Excel文件後發現,支援的比較少,文件也相對模糊一些,因此決定使用Laravel Excel,結合框架本身,實現簡單的使用。
開始
1、安裝larave-excel
composer require maatwebsite/excel
注意laravel版本號,目前支援5.8-8以及以上的版本,預設安裝的是3.1版本。
2、釋出配置
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
生成預設配置類——config/excel.php
,一般來說不需要更改配置。
使用
1、新建匯出類:
例如我匯出有關裝置的資訊,新建匯出裝置類DeviceExporter.php
,裝置表有id、name、user_id、created_at、updated_at
欄位:
<?php
namespace App\Admin\Extensions\Exporter;
use Dcat\Admin\Grid\Exporters\AbstractExporter;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class DeviceExporter extends AbstractExporter implements WithMapping, WithHeadings, FromCollection
{
use Exportable;
protected $fileName = '表格匯出測試';
protected $titles = [];
public function __construct()
{
$this->fileName = $this->fileName.'_'.Str::random(6).'.xlsx';//拼接下載檔名稱
$this->titles = ['id' => 'id', 'user_id' => '所屬使用者' ,'created_at'=>'建立時間','updated_at'=>'更新時間'];
parent::__construct();
}
public function export()
{
// TODO: Implement export() method.
$this->download($this->fileName)->prepare(request())->send();
exit;
}
public function collection()
{
// TODO: Implement collection() method.
return collect($this->buildData());
}
public function headings(): array
{
// TODO: Implement headings() method.
return $this->titles();
}
public function map($row): array
{
// TODO: Implement map() method.
return [
$row['id'],
$row['user_id'],
$row['created_at'],
$row['updated_at'],
];
}
}
可以看出,我們僅僅只需要關注map
和title
即可。
2、在控制器中使用:
$grid->export(new DeviceExporter());
重新整理頁面就有匯出按鈕在頁面右上角。
這裡又有一個問題,之前使用Easy Excel匯出資料,會有三種選項:全部、當前頁和選中的項,擔心使用laravel-excel會有問題,但是在AbstractExporter.php
中發現這樣的程式碼:
public function buildData(?int $page = null, ?int $perPage = null)
{
$model = $this->getGridModel();
// current page
if ($this->scope === Grid\Exporter::SCOPE_CURRENT_PAGE) {
$page = $model->getCurrentPage();
$perPage = $model->getPerPage();
}
$model->usePaginate(false);
if ($page && $this->scope !== Grid\Exporter::SCOPE_SELECTED_ROWS) {
$perPage = $perPage ?: $this->getChunkSize();
$model->forPage($page, $perPage);
}
$array = $this->grid->processFilter()->toArray();
$model->reset();
return $this->normalize($this->callBuilder($array));
}
匯出依賴於資料,buildData就是在處理資料。檢視SCOPE_CURRENT_PAGE
:
const SCOPE_ALL = 'all';
const SCOPE_CURRENT_PAGE = 'page';
const SCOPE_SELECTED_ROWS = 'selected';
剛好和我們所擔心的問題一致,因此可以斷定,無論使用什麼匯出擴充套件包,框架自身預設了這三種匯出方式。通過獲得當前頁、條數等資訊達到效果。並且在檢視相關方法時候發現,匯出方法裡的匯出會連同查詢條件一起進行資料匯出,也就是說,查詢完成後匯出的資料,是按照條件查詢的資料。
在測試三種匯出方法後,確定當前匯出沒有問題。
匯出關聯模型資料
上述的方式只能匯出現有的資料,對於需要匯出關聯模型資料來說就不行。那能不能實現匯出資料呢?可以,而且很簡單。
假如我有多臺裝置,例如:
| id | name | user_id | created_at | updated_at |
| ----- | ------- | -------- | ----------- | ----------- |
| 1 | 測試裝置1| 2 | ----------- | ----------- |
| 2 | 測試裝置2| 0 | ----------- | ----------- |
通過在public function map($row): array{}
中列印發現,如果有關聯資料,列印的資料會把關聯模型的資料列印出來,例如:
array:20 [▼
"id" => 1
"name" => "測試裝置1"
"user_id" => 2
"created_at" => "2021-08-23 14:25:46"
"updated_at" => "2021-08-23 14:26:10"
"user.id" => 2
"user.name" => "李大"
"user.created_at" => "2021-08-13 11:21:05"
"user.updated_at" => "2021-08-13 11:21:05"
]
而沒有關聯資料的則不顯示:
array:20 [▼
"id" => 2
"name" => "測試裝置2"
"user_id" => 0
"created_at" => "2021-08-23 14:25:46"
"updated_at" => "2021-08-23 14:26:10"
]
所以,需要匯出關聯模型的資料,我們可以直接修改map
程式碼為:
return [
$row['id'],
$row['user.name']??"",//為了防止無關聯資料包錯
$row['created_at'],
$row['updated_at'],
];
測試匯出,發現資料無誤,搞完手工。
總結
1、多個關聯關係資料依然適用,還是修改map
方法中的項;
2、建議複雜的資料處理還是單獨寫一個匯出元件,這樣程式碼層次更加清晰,資料處理也更簡單;
3、至於美化Excel頁面有需要的可以檢視相關文件進行;
4、還有更多複雜用法,例如按照選項進行自定義匯出,那個需要寫好路由和查詢方法,處理好匯出資料即可,這部分等我實驗一下再補充。
本作品採用《CC 協議》,轉載必須註明作者和本文連結