官方文档

https://docs.laravel-excel.com/3.1/getting-started/

GIT 地址

https://github.com/maatwebsite/Laravel-Excel

作为一个和 laravel 契合度很高的 excel 工具包,大家应该都是用过这个工具。特别是 2.x 版本几乎是用laravel框架都接触过,3.x 基本上全部重构,全网几乎找不到比较完善的教程,我就先抛砖引玉,大概把我用到的功能使用方式列一下,欢迎大家补充。

环境要求
  • PHP: ^7.0
  • Laravel: ^5.5

安装方式
  1. composer require maatwebsite/excel

因为目前 3.1 只支持 Laravel 5.5 以上,所以会自动注册。

excel 导入

新建导入文件,导入导出业务代码尽量不要和原来业务耦合。我们拿官网 user 模块举例

  1. php artisan make:import UsersImport

会在 app 目录下创建 Exports 目录

  1. .
  2. ├── app
  3. ├── Imports
  4. ├── UsersImport.php
  5. └── composer.json

UsersImport.php 代码内容

  1. <?php
  2. namespace App\Imports;
  3. use App\User;
  4. use Illuminate\Support\Facades\Hash;
  5. use Maatwebsite\Excel\Concerns\ToModel;
  6. class UsersImport implements ToModel
  7. {
  8. /**
  9. * @param array $row
  10. *
  11. * @return User|null
  12. */
  13. public function model(array $row)
  14. {
  15. return new User([
  16. 'name' => $row[0],
  17. 'email' => $row[1],
  18. 'password' => Hash::make($row[2]),
  19. ]);
  20. }
  21. }

业务控制器中调用

  1. use App\Imports\UsersImport;
  2. use Maatwebsite\Excel\Facades\Excel;
  3. use App\Http\Controllers\Controller;
  4. class UsersController extends Controller
  5. {
  6. public function import()
  7. {
  8. Excel::import(new UsersImport, 'users.xlsx');
  9. }
  10. }

需要说明的是,上面所用的模式是 toModel,不需要手动去调用 save 方法,如果需要手动控制存储过程,请使用下列方法。

  1. <?php
  2. namespace App\Imports;
  3. use App\User;
  4. use Illuminate\Support\Facades\Hash;
  5. //替换 toModel
  6. use Maatwebsite\Excel\Concerns\ToCollection;
  7. class UsersImport implements ToCollection
  8. {
  9. /**
  10. * 使用 ToCollection
  11. * @param array $row
  12. *
  13. * @return User|null
  14. */
  15. public function ToCollection(Collection $rows)
  16. {
  17. //如果需要去除表头
  18. unset($rows[0]);
  19. //$rows 是数组格式
  20. $this->createData($rows);
  21. }
  22. // 具体业务代码
  23. public function createData($rows)
  24. {
  25. //todo
  26. }
  27. }

Excel 导入基本功能到这基本完成,应该可以满足80%业务需求。如果有更多需求请继续阅读,下面将介绍分块导入、多表导入。

分块导入

如果 excel 数据量比较大,不适合一次性导入数据库,可以通过按量分块导入的方式节约内存。

按 1000 条为基准取出导入

  1. namespace App\Imports;
  2. use App\User;
  3. use Maatwebsite\Excel\Concerns\ToModel;
  4. //新增
  5. use Maatwebsite\Excel\Concerns\WithBatchInserts;
  6. use Maatwebsite\Excel\Concerns\WithChunkReading;
  7. class UsersImport implements ToModel, WithBatchInserts, WithChunkReading
  8. {
  9. public function model(array $row)
  10. {
  11. return new User([
  12. 'name' => $row[0],
  13. ]);
  14. }
  15. //批量导入1000条
  16. public function batchSize(): int
  17. {
  18. return 1000;
  19. }
  20. //以1000条数据基准切割数据
  21. public function chunkSize(): int
  22. {
  23. return 1000;
  24. }
  25. }

需要注意的是 批量导入 只支持 ToModel 模式,如果你需要对数据进行更改,建议先批量导入临时表,再修改数据导入业务相关表。

多 sheet 导入

和导出比较类似,需要两步操作,第一步读取整体 excel 结构,第二步完成对应表数据导入。

第一个文件 UsersImport.php

  1. namespace App\Imports;
  2. use Maatwebsite\Excel\Concerns\WithMultipleSheets;
  3. class UsersImport implements WithMultipleSheets
  4. {
  5. public function sheets(): array
  6. {
  7. //这里需要注意的是键,这个键可以是sheet表的名称,比如 'sheet1'=> new FirstSheetImport()
  8. return [
  9. 0 => new FirstSheetImport(),
  10. 1 => new SecondSheetImport(),
  11. ];
  12. }
  13. }

这里我没有找到获取所有 sheet 的方法,所以只能一个个指定,如果你调用的方法是一致的,可以参考以下我的写法。如果你有更好的方式,欢迎交流。

  1. public function sheets(): array
  2. {
  3. $sheet = [];
  4. for ($i=1; $i<=26; $i++) {
  5. $sheet[$i] = new CustomSheetImport();
  6. }
  7. return $sheet;
  8. }

第二个文件处理数据

  1. namespace App\Imports;
  2. use Illuminate\Support\Collection;
  3. use Maatwebsite\Excel\Concerns\ToCollection;
  4. class FirstSheetImport implements ToCollection
  5. {
  6. public function collection(Collection $rows)
  7. {
  8. //todo
  9. }
  10. }

其他比如数据验证之类的方法我觉得还是不要使用它提供的方式,大部分业务环境不需要这些额外繁琐的东西。
LNCODE
如果你有其他需要分享的功能模块欢迎在评论提出,我会更新文档。