版本
- php 7.2
- ubuntu 18
- laravel 6.18
- laravel-admin 1.8
- maatwebsite/excel 3.1
步驟
- 新增匯入資料按鈕
- 引入
maatwebsite/excel
包處理資料
新增匯入資料按鈕
執行下面的命令建立一個普通操作類:
php artisan admin:action Tenant\\ImportTenant --name="匯入資料"
生成的類檔案 app/Admin/Actions/Tenant/ImportTenant.php
:
<?php
namespace App\Admin\Actions\Tenant;
use Encore\Admin\Actions\Action;
use Illuminate\Http\Request;
class ImportTenant extends Action
{
protected $selector = '.import-tenant';
public function handle(Request $request)
{
// $request ...
return $this->response()->success('Success message...')->refresh();
}
public function html()
{
return <<<HTML
<a class="btn btn-sm btn-default import-tenant">匯入資料</a>
HTML;
}
}
修改這個類,提供上傳檔案的功能,並加上處理資料的邏輯:
<?php
namespace App\Admin\Actions\Tenant;
use Encore\Admin\Actions\Action;
use Illuminate\Http\Request;
class ImportTenant extends Action
{
protected $selector = '.import-tenant';
public function handle(Request $request)
{
// 下面的程式碼獲取到上傳的檔案,然後使用`maatwebsite/excel`等包來處理上傳你的檔案,儲存到資料庫
$request->file('file');
return $this->response()->success('匯入完成!')->refresh();
}
public function form()
{
$this->file('file', '請選擇檔案');
}
public function html()
{
return <<<HTML
<a class="btn btn-sm btn-default import-tenant"><i class="fa fa-upload"></i>匯入資料</a>
HTML;
}
}
修改app/Admin/Controller/TenantController.php
, 將匯入操作加入到表格的工具條中
class TenantController extends AdminController
{
protected $title = '租客';
protected function grid()
{
$grid = new Grid(new Tenant());
.
.
.
// 將匯入操作加入到表格的工具條中
$grid->tools(function (Grid\Tools $tools) {
$tools->append(new ImportTenant());
});
}
到這裡完成新增匯入按鈕。
引入 maatwebsite/excel
包處理資料
安裝包
composer require maatwebsite/excel
建立一個匯入類
php artisan make:import TenantsImport --model=Models\\Tenant
生成的類檔案app\Imports\TenantImport.php
:
<?php
namespace App\Imports;
use App\Models\Tenant;
use Maatwebsite\Excel\Concerns\ToModel;
class TenantsImport implements ToModel
{
public function model(array $row)
{
return new Tenant([
//
]);
}
}
修改類檔案,設定欄位對應的列
use App\Models\Tenant;
use Maatwebsite\Excel\Concerns\ToModel;
class TenantsImport implements ToModel
{
public function model(array $row)
{
return new Tenant([
'name' => $row[0],
'phone' => $row[1],
'id_card' => $row[2]
]);
}
}
為了不讀取表頭,通過實現WithStartRow
介面來設定從第二行開始讀取資料
namespace App\Imports;
·
·
use Maatwebsite\Excel\Concerns\WithStartRow;
class TenantsImport implements ToModel, WithStartRow
{
·
·
·
// 從2行開始讀取資料
public function startRow(): int
{
return 2;
}
}
設定資料驗證規則
<?php
namespace App\Imports;
.
.
.
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithValidation;
class TenantsImport implements ToModel, WithStartRow, WithValidation
{
use Importable;
.
.
.
// 驗證
public function rules(): array
{
return [
'0' => 'required',
];
}
}
自定義驗證資訊
namespace App\Imports;
.
.
.
class TenantsImport implements ToModel, WithStartRow, WithValidation
{
.
.
.
// 自定義驗證資訊
public function customValidationMessages()
{
'0.required' => '姓名未填',
}
}
在app\Admin\Actions\Tenant\ImportTenant.php
呼叫匯入
namespace App\Admin\Actions\Tenant;
.
.
use App\Imports\TenantsImport;
class ImportTenant extends Action
{
protected $selector = '.import-tenant';
public function handle(Request $request)
{
// 下面的程式碼獲取到上傳的檔案,然後使用`maatwebsite/excel`等包來處理上傳你的檔案,儲存到資料庫
$request->file('file');
$import = new TenantsImport();
$import->import($request->file('file'));
return $this->response()->success('匯入完成!')->refresh();
}
.
.
.
}
跳過驗證失敗的行
app\Imports\TenantImport.php
:
namespace App\Imports;
.
.
.
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\SkipsFailures;
class TenantsImport implements ToModel, WithStartRow, WithValidation, SkipsOnFailure
{
use Importable, SkipsFailures;
.
.
.
}
收集驗證失敗的行資訊並顯示
app\Admin\Actions\Tenant\ImportTenant.php
:
namespace App\Admin\Actions\Tenant;
.
.
use App\Imports\TenantsImport;
class ImportTenant extends Action
{
protected $selector = '.import-tenant';
public function handle(Request $request)
{
// 下面的程式碼獲取到上傳的檔案,然後使用`maatwebsite/excel`等包來處理上傳你的檔案,儲存到資料庫
$import = new TenantsImport();
$import->import($request->file('file'));
$str = "";
foreach ($import->failures() as $failure) {
$str .= ' 第'. $failure->row() . '行 失敗原因:' . implode(' ', $failure->errors()) . '<br> 行資料:' . implode(' ', $failure->values()). '<br>';
}
if ($str !== '') {
return $this->response()->error($str)->topFullWidth()->timeout(7000000);
}
return $this->response()->success('匯入完成!')->refresh();
}
.
.
.
}
參考
本作品採用《CC 協議》,轉載必須註明作者和本文連結