前一段需要專案中需要通過Excel匯入使用者,之前用過phpexcel,總感覺太過繁瑣,印象中phpexcel也很久沒更新,看到專案中有使用Maatwebsite\Excel
,便嘗試使用一下。
安裝
composer require maatwebsite/excel
匯入
生成匯入類
php artisan make:import AdminsImport --model=Admin
會看到app下面生成了Imports資料夾。
完善業務邏輯
<?php
namespace App\Imports;
use App\Models\Admin;
use function EasyWeChat\Kernel\Support\str_random;
use Maatwebsite\Excel\Concerns\ToModel;
class AdminsImport implements ToModel
{
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
//過濾表頭和空行,我這邊表頭的第一個單元格是id,具體自行調整
if (empty($row[0]) || $row[0] == 'id') {
return null;
}
return new Admin([
'username' => $row[2],
'password' => bcrypt($row[3]),
'api_token' => str_random(60),
]);
}
}
匯入任務
<?php
namespace App\Console\Commands;
use App\Imports\AdminsImport;
use Illuminate\Console\Command;
use Maatwebsite\Excel\Facades\Excel;
class ImportAdmin extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'importAdmin';
/**
* The console command description.
*
* @var string
*/
protected $description = '匯入admin';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Excel::import(new AdminsImport(), storage_path('files/export.xlsx'));
$this->info($this->description.'完成');
}
}
其他邏輯
當然,可能業務必不僅僅是寫入資料,可能有一些設計具體業務的操作,那麼你可以這樣操作。
<?php
namespace App\Imports;
use App\Models\Admin;
use function EasyWeChat\Kernel\Support\str_random;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Collection;
class AdminsImport implements ToCollection
{
public function collection(Collection $rows)
{
//如果需要去除表頭
unset($rows[0]);
//$rows 是陣列格式
return $this->createData($rows);
}
public function createData($rows)
{
$success = 0;
foreach ($rows as $row) {
$row[0] = (int) $row[0];
if (empty($row[0])) {
continue;
}
(new Admin())->create(
[
'username' => $row[2],
'name' => $row[2],
'password' => bcrypt($row[3]),
'api_token' => str_random(60),
]
);
// 其他業務程式碼
$success++;
}
return $success.'-'.count($rows);
}
}
執行
php7.2 artisan importAdmin
總的來說,使用起來還是簡單明瞭的。
more
具體匯入實現可以搜尋Maatwebsite\Excel\Excel
檢視,裡面還有匯出、以佇列方式匯入等,支援的格式也是多種多樣,具體程式碼如下,功能還是很強大的,足夠應付日常需求了。
<?php
namespace Maatwebsite\Excel;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Files\Filesystem;
use Maatwebsite\Excel\Files\TemporaryFile;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\PendingDispatch;
use Maatwebsite\Excel\Helpers\FileTypeDetector;
class Excel implements Exporter, Importer
{
use RegistersCustomConcerns;
const XLSX = 'Xlsx';
const CSV = 'Csv';
const TSV = 'Csv';
const ODS = 'Ods';
const XLS = 'Xls';
const SLK = 'Slk';
const XML = 'Xml';
const GNUMERIC = 'Gnumeric';
const HTML = 'Html';
const MPDF = 'Mpdf';
const DOMPDF = 'Dompdf';
const TCPDF = 'Tcpdf';
/**
* @var Writer
*/
protected $writer;
/**
* @var QueuedWriter
*/
protected $queuedWriter;
/**
* @var Filesystem
*/
protected $filesystem;
/**
* @var Reader
*/
private $reader;
/**
* @param Writer $writer
* @param QueuedWriter $queuedWriter
* @param Reader $reader
* @param Filesystem $filesystem
*/
public function __construct(
Writer $writer,
QueuedWriter $queuedWriter,
Reader $reader,
Filesystem $filesystem
) {
$this->writer = $writer;
$this->reader = $reader;
$this->filesystem = $filesystem;
$this->queuedWriter = $queuedWriter;
}
/**
* {@inheritdoc}
*/
public function download($export, string $fileName, string $writerType = null, array $headers = [])
{
return response()->download(
$this->export($export, $fileName, $writerType)->getLocalPath(),
$fileName,
$headers
)->deleteFileAfterSend(true);
}
/**
* {@inheritdoc}
*/
public function store($export, string $filePath, string $diskName = null, string $writerType = null, $diskOptions = [])
{
if ($export instanceof ShouldQueue) {
return $this->queue($export, $filePath, $diskName, $writerType, $diskOptions);
}
$temporaryFile = $this->export($export, $filePath, $writerType);
$exported = $this->filesystem->disk($diskName, $diskOptions)->copy(
$temporaryFile,
$filePath
);
$temporaryFile->delete();
return $exported;
}
/**
* {@inheritdoc}
*/
public function queue($export, string $filePath, string $disk = null, string $writerType = null, $diskOptions = [])
{
$writerType = FileTypeDetector::detectStrict($filePath, $writerType);
return $this->queuedWriter->store(
$export,
$filePath,
$disk,
$writerType,
$diskOptions
);
}
/**
* {@inheritdoc}
*/
public function raw($export, string $writerType)
{
$temporaryFile = $this->writer->export($export, $writerType);
$contents = $temporaryFile->contents();
$temporaryFile->delete();
return $contents;
}
/**
* {@inheritdoc}
*/
public function import($import, $filePath, string $disk = null, string $readerType = null)
{
$readerType = FileTypeDetector::detect($filePath, $readerType);
$response = $this->reader->read($import, $filePath, $readerType, $disk);
if ($response instanceof PendingDispatch) {
return $response;
}
return $this;
}
/**
* {@inheritdoc}
*/
public function toArray($import, $filePath, string $disk = null, string $readerType = null): array
{
$readerType = FileTypeDetector::detect($filePath, $readerType);
return $this->reader->toArray($import, $filePath, $readerType, $disk);
}
/**
* {@inheritdoc}
*/
public function toCollection($import, $filePath, string $disk = null, string $readerType = null): Collection
{
$readerType = FileTypeDetector::detect($filePath, $readerType);
return $this->reader->toCollection($import, $filePath, $readerType, $disk);
}
/**
* {@inheritdoc}
*/
public function queueImport(ShouldQueue $import, $filePath, string $disk = null, string $readerType = null)
{
return $this->import($import, $filePath, $disk, $readerType);
}
/**
* @param object $export
* @param string|null $fileName
* @param string $writerType
*
* @throws \PhpOffice\PhpSpreadsheet\Exception
* @return TemporaryFile
*/
protected function export($export, string $fileName, string $writerType = null): TemporaryFile
{
$writerType = FileTypeDetector::detectStrict($fileName, $writerType);
return $this->writer->export($export, $writerType);
}
}
最後,感謝下面這一篇站內文章讓我快速上手。
最後,附上Laravel Excel 文件:
本作品採用《CC 協議》,轉載必須註明作者和本文連結