Laravel 实现文件 导入/导出 功能
本文推荐使用和 Laravel 契合度很高的 maatwebsite/excel 工具包。
2.x 版本
2.x 版本国内使用率较高,使用简单。
环境要求
- PHP version >= 5.3.7
- Laravel >= 4.1
安装配置
安装 maatwebsite/excel 工具包:
composer require maatwebsite/excel ~2.1
在 config/app.php 中注册服务提供者到 providers 数组:
Maatwebsite\Excel\ExcelServiceProvider::class,
在 config/app.php 中注册门面到 aliases 数组:
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
导出示例
use Excel;
$cellData = [
['学号','姓名','成绩'],
['10001','AAAAA','99'],
['10002','BBBBB','92'],
['10003','CCCCC','95'],
['10004','DDDDD','89'],
['10005','EEEEE','96'],
];
Excel::create('学生成绩', function($excel) use ($cellData){
$excel->sheet('score', function($sheet) use ($cellData){
$sheet->rows($cellData);
});
})->export('xls');
导入示例
use Excel;
$filePath = 'filePath';
Excel::load($filePath, function($reader) {
$data = $reader->all();
dd($data);
});
3.x 版本
3.x 改版较大,基本重构。底层通过 Export 对象驱动,入口自定义 Export 类,实例化 FromCollection 接口,继承Exportale 特性。
环境要求
- PHP >= 7.0
- Laravel >= 5.5
安装配置
安装 maatwebsite/excel 工具包:
composer require maatwebsite/excel ~3.1
导出示例
新建导出数据表 user 的文件:
php artisan make:export UsersExport --model=User
app 目录下创建 Exports 目录:
.
├── app
│ ├── Exports
│ │ ├── UsersExport.php
│
└── composer.json
UsersExport.php 文件内容:
<?php
namespace App\Exports;
use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersExport implements FromCollection
{
public function collection()
{
return User::all();
}
}
业务调用:
<?php
use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;
class UsersController extends Controller
{
public function export()
{
return Excel::download(new UsersExport, 'users.xlsx');
}
}
上述示例中,UsersExport 继承了 FromCollection 类,在 collection 方法中查询了 user 表,并导出 user 表数据。
但是在一些业务逻辑中,我们想直接导出自定义数组,这里我们可以用到 maatwebsite/excel 中 FromArray 类来实现此功能。
创建 CommonExport.php 导出文件:
php artisan make:export CommonExport
app 目录下创建 Exports 目录:
.
├── app
│ ├── Exports
│ │ ├── UsersExport.php
│ │ ├── CommonExport.php
│
└── composer.json
CommonExport.php 文件内容:
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromArray;
class CommonExport implements FromArray
{
public function array(): array
{
$data = [
['表题1', '表题2', '表题3'],
['value1', 'value2', 'value3'],
['value1', 'value2', 'value3'],
['value1', 'value2', 'value3']
];
return $data;
}
}
业务调用:
<?php
namespace App\Http\Controllers;
use App\Exports\CommonExport;
use Maatwebsite\Excel\Facades\Excel;
class DemoController
{
public function demo()
{
return Excel::download(new CommonExport(), 'demo.xlsx');
}
}
上述示例中,CommonExport.php 文件我们可以做下封装:
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromArray;
# 自动适应单元格宽
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
class CommonExport implements FromArray, ShouldAutoSize
{
protected $lists;
protected $headers;
public function __construct(array $headers, array $lists)
{
$this->lists = $lists;
$this->headers = $headers;
}
public function array(): array
{
return $this->lists;
}
public function headings(): array
{
return $this->headers;
}
}
在业务层调用:
<?php
namespace App\Http\Controllers;
use App\Exports\CommonExport;
use Maatwebsite\Excel\Facades\Excel;
class DemoController
{
public function demo()
{
$headers = ['表题1', '表题2', '表题3'];
$lists = [
['value1', 'value2', 'value3'],
['value1', 'value2', 'value3'],
['value1', 'value2', 'value3'],
['value1', 'value2', 'value3']
];
return Excel::download(new CommonExport($headers, $lists), 'demo.xlsx');
}
}
注意,在上述的 CommonExport 封装类中,我们同时继承使用了自动适应单元格宽的 ShouldAutoSize 类。
Maatwebsite\Excel 工具包中提供了很多方法,如:自动适应单元格宽、单元格格式化、导出多 sheet、设置单元格高度以及垂直居中,字体颜色、背景色等、导出图片等等方法。这里我们就不一一介绍了,若使用可参考官方提供的文档。
导入示例
新建导入数据库 user 表数据的文件:
php artisan make:import UsersImport --model=User
app 目录下创建 Imports 目录:
.
├── app
│ ├── Imports
│ │ ├── UsersImport.php
│
└── composer.json
UsersImport.php 代码内容:
<?php
namespace App\Imports;
use App\User;
use Illuminate\Support\Facades\Hash;
use Maatwebsite\Excel\Concerns\ToModel;
class UsersImport implements ToModel
{
/**
* @param array $row
*
* @return User|null
*/
public function model(array $row)
{
return new User([
'name' => $row[0],
'email' => $row[1],
'password' => Hash::make($row[2]),
]);
}
}
业务调用:
use App\Imports\UsersImport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;
class UsersController extends Controller
{
public function import()
{
Excel::import(new UsersImport, 'users.xlsx');
}
}
需要说明的是,上面所用的模式是 toModel,不需要手动去调用 save 方法,如果需要手动控制存储过程,请使用下列方法:
<?php
namespace App\Imports;
use App\User;
use Illuminate\Support\Facades\Hash;
//替换 toModel
use Maatwebsite\Excel\Concerns\ToCollection;
class UsersImport implements ToCollection
{
/**
* 使用 ToCollection
* @param array $row
*
* @return User|null
*/
public function ToCollection(Collection $rows)
{
//如果需要去除表头
unset($rows[0]);
//$rows 是数组格式
$this->createData($rows);
}
public function createData($rows)
{
//todo
}
}
以上示例中,我们使用 UsersImport 类直接添加数据到 user 表。
但是在一些业务逻辑中,我们想直接取出 Excel 表格中的数据,这里我们可以使用到 maatwebsite/excel 中 ToArray 类来实现此功能。
创建 CommonExport.php 导入文件:
php artisan make:import CommonImport
app 目录下创建 Imports 目录:
.
├── app
│ ├── Imports
│ │ ├── UsersImport.php
│ │ ├── CommonImport.php
│
└── composer.json
CommonImport.php 文件内容:
<?php
namespace App\Imports;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\ToArray;
class CommonImport implements ToArray
{
public function Array(Array $tables)
{
return $tables;
}
}
业务调用:
<?php
namespace App\Http\Controllers;
use App\Imports\CommonImport;
use Maatwebsite\Excel\Facades\Excel;
class DemoController
{
public function demo()
{
$file = 'D:\WWW\Study\Laravel\public\data\demo.xlsx';
$array = Excel::toArray(new CommonImport, $file);
dd($array);
}
}
与导出一样,Maatwebsite\Excel 工具包中也提供了很多其他导入功能,如:分块导入、多 sheet 导入等方法。若使用可参考官方提供的文档。
问题汇总
因项目环境配置不同,以下解决方法仅供参考。
导出空文件
date: 2020-04-13
Nginx Version: 1.14.0
PHP Version: v7.1.33
Laravel Version: 5.5
maatwebsite/excel Version: 3.1
主要原因:版本兼容问题。继承使用了自动适应单元格宽的 ShouldAutoSize 类。