Sivo 悉见

生命周期

匿名 · 更新于 2021/6/28

介绍

在您的应用程序中使用包时,最好了解包在幕后的功能。了解幕后工作将使您在使用该工具的最大潜力时感到更加自在和自信。

这个页面的目标是让你对 Laravel Excel 的工作方式有一个高层次的概述。

#导出生命周期概述

本节将尝试向您概述导出的幕后工作方式。

#导出对象

一切从Export对象开始该对象封装了您的整个导出逻辑。它既配置又处理导出逻辑。

导出对象的一个​​简单示例是:

<?php

namespace App</span>Exports;

use App</span>User; use Maatwebsite</span>Excel</span>Concerns</span>FromCollection;

class UsersExport implements FromCollection { public function collection() { return User::all(); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14

如果您想了解更多关于出口对象,去的架构页出口对象

#传递导出对象

接下来,Export 对象将传递给 Laravel Excel 包。这个的主要入口点是Maatwebsite/Excel/Excel类。可以通过多种方式调用此类。

#正面

Excel使用类的最简单方法是使用Maatwebsite\Excel\Facades\Excel外观。如果您使用自动发现 (打开新窗口),您可以\Excel直接使用别名而不是使用完全限定的命名空间。

#依赖注入

Maatwebsite/Excel/Excel在控制器的情况下,您可以通过构造函数注入或方法注入将管理器类注入到您的类中。

<?php
use App\Exports\UsersExport;
use Maatwebsite\Excel\Excel;

class ExportController { private $excel;

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">__construct</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span>Excel <span class="token variable" style="color: rgb(126, 198, 153);">$excel</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token variable" style="color: rgb(126, 198, 153);">$this</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token property" style="color: rgb(248, 197, 85); font-style: italic !important;">excel</span> <span class="token operator" style="color: rgb(103, 205, 204);">=</span> <span class="token variable" style="color: rgb(126, 198, 153);">$excel</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">exportViaConstructorInjection</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">return</span> <span class="token variable" style="color: rgb(126, 198, 153);">$this</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token property" style="color: rgb(248, 197, 85); font-style: italic !important;">excel</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token function" style="color: rgb(240, 141, 73);">download</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">new</span> <span class="token class-name" style="color: rgb(248, 197, 85);">UsersExport</span><span class="token punctuation" style="color: rgb(204, 204, 204);">,</span> <span class="token single-quoted-string string" style="color: rgb(126, 198, 153);">&#39;users.xlsx&#39;</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">exportViaMethodInjection</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span>Excel <span class="token variable" style="color: rgb(126, 198, 153);">$excel</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">return</span> <span class="token variable" style="color: rgb(126, 198, 153);">$excel</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token function" style="color: rgb(240, 141, 73);">download</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">new</span> <span class="token class-name" style="color: rgb(248, 197, 85);">UsersExport</span><span class="token punctuation" style="color: rgb(204, 204, 204);">,</span> <span class="token single-quoted-string string" style="color: rgb(126, 198, 153);">&#39;users.xlsx&#39;</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

#合同

您还可以使用该Maatwebsite\Excel\Exporter接口将更多内容与具体的 Excel 管理器实现分离。契约提供与Excel相同的方法这将使得在您的单元测试中更容易地排除导出器。Exporter合同可以通过构造或在控制器的方法或者注入。

use App\Exports\UsersExport;
use Maatwebsite\Excel\Exporter;

class ExportsController { private $exporter;

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">__construct</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span>Exporter <span class="token variable" style="color: rgb(126, 198, 153);">$exporter</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token variable" style="color: rgb(126, 198, 153);">$this</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token property" style="color: rgb(248, 197, 85); font-style: italic !important;">exporter</span> <span class="token operator" style="color: rgb(103, 205, 204);">=</span> <span class="token variable" style="color: rgb(126, 198, 153);">$exporter</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">export</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">return</span> <span class="token variable" style="color: rgb(126, 198, 153);">$this</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token property" style="color: rgb(248, 197, 85); font-style: italic !important;">exporter</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token function" style="color: rgb(240, 141, 73);">download</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">new</span> <span class="token class-name" style="color: rgb(248, 197, 85);">UsersExport</span><span class="token punctuation" style="color: rgb(204, 204, 204);">,</span> <span class="token single-quoted-string string" style="color: rgb(126, 198, 153);">&#39;users.xlsx&#39;</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#容器绑定

如果您想Maatwebsite\Excel\Excel通过容器绑定将管理器绑定到您自己的类,您可以使用excel容器绑定。

$this->app->bind(YourCustomExporter::class, function() {
    return new YourCustomExporter($this->app['excel']);
});
1
2
3

#可输出性状

如果你更喜欢一点魔法,你可以Maatwebsite\Excel\Concerns\Exportable在你的Export对象中使用trait 这个特性将公开几个方法,使直接导出Export对象成为可能

namespace App\Exports;

use App</span>User; use Maatwebsite</span>Excel</span>Concerns</span>FromCollection; use Maatwebsite</span>Excel</span>Concerns</span>Exportable;

class UsersExport implements FromCollection { use Exportable;

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">collection</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">return</span> User<span class="token punctuation" style="color: rgb(204, 204, 204);">:</span><span class="token punctuation" style="color: rgb(204, 204, 204);">:</span><span class="token function" style="color: rgb(240, 141, 73);">all</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

您现在可以下载导出而不需要facadeExcel管理器。

return (new UsersExport)->download('users.xlsx');
1

exportables文档中阅读有关可导出特征的更多信息

#处理导出对象

#写入器类型检测

使用上述方法之一将Export对象传递Excel管理器后,它将尝试找出需要将其生成到哪个导出。这将基于文件的扩展名,显式传递的编写器类型。您可以在 部分的excel.php配置中找到写入器类型映射的扩展extension_detector如果无法检测到写入器类型,Maatwebsite\Excel\Exceptions\NoTypeDetectedException则会引发异常并停止导出过程。

#开始写作过程

然后,Excel经理会将处理委托给Maatwebsite\Excel\Writer的第一个动作Writer是注册已注册的事件侦听器。接下来它将创建一个新PhpOffice\PhpSpreadsheet\Spreadsheet实例,我们将使用实例将我们的Export对象转换为。

引发的第一个事件是BeforeExport事件。这是在Spreadsheet创建实例后立即引发的,并允许提前访问它。

#多张

接下来Writer将通过检查Maatwebsite\Excel\Concerns\WithMultipleSheets问题来确定是否配置了多个工作表

然后它将对每个工作表的进一步处理委托给Maatwebsite\Excel\Sheet班级。

#加工板材

Sheet课堂上,最繁重的工作发生了。它首先会创建一个PhpOffice\PhpSpreadsheet\Worksheet\Worksheet实例。然后它将引发BeforeSheet事件,允许您在工作表处理开始之前的那一刻进行挂钩。

然后,它会决定什么样的出口,我们正在处理:FromQueryFromArrayFromCollectionFromView基于此,它将启动连接的导出过程。

  • FromView将呈现的Blade视图传递给 PhpSpreadsheet 的Html阅读器。该阅读器会将表格 html 转换为 Excel 单元格。它还处理一些内联样式(颜色和背景颜色)和 col/rowspans。
  • 使用传递查询FromQuery将自动分块,并且每个块都将附加到工作表中。分块是为了限制它需要保留在内存中的 Eloquent 对象的数量。它大大减少了内存使用。
  • 整个 Collection 数组将直接附加到工作表中。

Sheet开始追加记录时,map()如果使用了WithMapping关注点,它将首先调用该方法这允许Export对象在插入之前格式化数据。

然后它将处理列格式(WithColumnFormatting关注)和单元格自动调整大小(ShouldAutoSize)。

要关闭工作表处理,它将引发一个AfterSheet事件。

#传递到 PhpSpreadsheet

处理完纸张后,将开始写入过程。写入过程通过引发BeforeWriting事件开始这使您可以进入写作过程。接下来,我们将PhpSpreadsheet Writer根据确定的编写器类型创建一个新的。然后它将它保存到一个临时文件并将该文件路径返回给Excel管理器。

#创建响应

Excel经理主要有两种类型的响应,它要么启动下载进程或将存储到磁盘文件。

#下载文件

我们将获取由 返回的临时文件Writer并使用 LaravelResponseFactory创建一个Symfony\Component\HttpFoundation\BinaryFileResponse在您的控制器中返回此响应时,它将开始下载。

#存储文件

文件的存储将由 Laravel 的Filesystem默认情况下,文件将存储在您的default磁盘上,但您也可以通过该Excel::store()方法传递自定义磁盘

#导入生命周期概述

本节将尝试为您概述导入的幕后工作方式。

#导入对象

一切从Import对象开始该对象封装了您的整个导入逻辑。它既配置又处理导入逻辑。

导入对象的一个​​简单示例是:

namespace App\Imports;

use App</span>User; use Illuminate</span>Support</span>Collection; use Maatwebsite</span>Excel</span>Concerns</span>ToCollection;

class UsersImport implements ToCollection { public function collection(Collection $rows) { foreach ($rows as $row) { User::create([ 'name' => $row[0], ]); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

如果您想了解更多关于进口对象,去的架构页面进口对象

#传递导入对象

接下来,Import 对象将传递给 Laravel Excel 包。这个的主要入口点是Maatwebsite/Excel/Excel类。可以按照导出生命周期中概述的相同方式调用此类。

#合同

您还可以使用该Maatwebsite\Excel\Importer接口将更多内容与具体的 Excel 管理器实现分离。契约提供与Excel相同的方法这将使得在您的单元测试中更容易地删除导入程序。Importer合同可以通过构造或控制器的方法中任一注射。

use App\Imports\UsersImport;
use Maatwebsite\Excel\Importer;

class ImportsController { private $importer;

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">__construct</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span>Importer <span class="token variable" style="color: rgb(126, 198, 153);">$importer</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token variable" style="color: rgb(126, 198, 153);">$this</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token property" style="color: rgb(248, 197, 85); font-style: italic !important;">importer</span> <span class="token operator" style="color: rgb(103, 205, 204);">=</span> <span class="token variable" style="color: rgb(126, 198, 153);">$importer</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

<span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">public</span> <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">function</span> <span class="token function" style="color: rgb(240, 141, 73);">import</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">{</span>
    <span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">return</span> <span class="token variable" style="color: rgb(126, 198, 153);">$this</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token property" style="color: rgb(248, 197, 85); font-style: italic !important;">importer</span><span class="token operator" style="color: rgb(103, 205, 204);">-</span><span class="token operator" style="color: rgb(103, 205, 204);">&gt;</span><span class="token function" style="color: rgb(240, 141, 73);">import</span><span class="token punctuation" style="color: rgb(204, 204, 204);">(</span><span class="token keyword" style="color: rgb(204, 153, 205); font-style: italic !important;">new</span> <span class="token class-name" style="color: rgb(248, 197, 85);">UsersImport</span><span class="token punctuation" style="color: rgb(204, 204, 204);">,</span> <span class="token single-quoted-string string" style="color: rgb(126, 198, 153);">&#39;users.xlsx&#39;</span><span class="token punctuation" style="color: rgb(204, 204, 204);">)</span><span class="token punctuation" style="color: rgb(204, 204, 204);">;</span>
<span class="token punctuation" style="color: rgb(204, 204, 204);">}</span>

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#可导入特性

如果你更喜欢一点魔法,你可以Maatwebsite\Excel\Concerns\Importable在你的Import对象中使用trait 这个特性将公开几个方法,使直接导入Import对象成为可能

namespace App\Imports;

use App</span>User; use Maatwebsite</span>Excel</span>Concerns</span>ToCollection; use Maatwebsite</span>Excel</span>Concerns</span>Importable;

class UsersImport implements ToCollection { use Importable;

<span class="token punctuation" style="color: rgb(204, 204, 204);">.</span><span class="token punctuation" style="color: rgb(204, 204, 204);">.</span><span class="token punctuation" style="color: rgb(204, 204, 204);">.</span>

}

1
2
3
4
5
6
7
8
9
10
11
12

您现在可以导入而无需facadeExcel管理器。

(new UsersImport)->import('users.xlsx');
1

在可导入文档中阅读有关可导入特征的更多信息

#处理导入对象

#阅读器类型检测

在使用上述方法之一将Import对象传递Excel管理器后,它会尝试找出它是什么读取器类型。这将基于文件的扩展名或显式传递的读取器类型。您可以在excel.php配置中找到阅读器类型映射的扩展extension_detector部分。如果无法检测到读取器类型,Maatwebsite\Excel\Exceptions\NoTypeDetectedException则会引发异常并停止导入过程。

#开始阅读过程

然后,Excel经理会将处理委托给Maatwebsite\Excel\Reader的第一个动作Reader是注册已注册的事件侦听器。它会将文件从 Laravel 复制Filesystem到本地文件系统,以便 PhpSpreadsheet 可以读取它。接下来,它将Reader根据给定的阅读器类型创建一个 PhpSpreadsheet ,并将文件加载到一个PhpOffice\PhpSpreadsheet\Spreadsheet实例中。

接下来它将创建一个新PhpOffice\PhpSpreadsheet\Spreadsheet实例,我们将使用它来读取我们的Import对象。

引发的第一个事件是BeforeImport事件。这是在Spreadsheet加载实例后立即引发的,并允许提前访问它。

#多张

接下来我们将确定我们是否正在处理多个工作表。这是基于WithMultipleSheets担忧来完成的

#加工板材

然后处理每个 Sheet。这个过程通过引发BeforeSheet事件开始。然后它将其导入到一个集合、一个数组或将每一行作为 Eloquent 模型处理。

  • 使用时ToModel,每个返回的模型都将通过 Eloquent 持久化。与 结合使用时WithBatchInserts,它将延迟持久化,直到批处理完成,然后将它们作为一个批处理插入到数据库中。
  • 使用ToCollection或 时ToArray,整个数据集将传递给导入方法,用户可以自行决定如何使用它。

通过引发AfterSheet事件结束工作表处理