系列文章目录
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录)
前言
学习thinkphp6(tp6)的queue队列插入时,由于网上大部分教程层次不齐,有些代码更是扯,只写做到少量数据的插入方式,所以我自己成功后给大家提供一种方式去插入数据
提示:以下是本篇文章正文内容,下面案例可供参考
一、使用的工具和一些配置
以下均为windows环境,linux另寻他法,可做参考
1.安装TP6(自己去手册下载,这个不会我没办法)
2.redis,宝塔自带redis直接拿来用就行
3.需要的扩展如下;
viwe和queue,PhpOffice
view扩展
代码如下 : composer require topthink/think-view
queue扩展
代码如下: composer require topthink/think-queue
phpoffice扩展(此扩展用来读取excel表格)
代码如下: composer require phpoffice/phpspreadsheet
3。配置
在database修改数据库改成自己的(都上队列了这点应该不用交)
在config的queue.php中修改成如下配置
代码如下(示例):
return [
‘default’ => ‘redis’,//修改成redis
‘connections’ => [
‘sync’ => [
‘type’ => ‘sync’,
二、使用步骤
1.明确下概念
任务类不需继承任何类,如果这个类只有一个任务,那么就只需要提供一个fire
方法就可以了,如果有多个小任务,就写多个方法,下面发布任务的时候会有区别
每个方法会传入两个参数 think\queue\Job $job
(当前的任务对象) 和 $data
(发布任务时自定义的数据)
还有个可选的任务失败执行的方法 failed
传入的参数为$data
(发布任务时自定义的数据)
2.控制器代码,代码来喽
先上德狗!
遍历速度很慢很正常,16G内存差不多遍历了4到6分钟左右,很正常注意报错信息,上传成功提示你为成功
控制器代码为
控制器代码为:
在这里插入代码片
```<?php
namespace app\controller;
use PhpOffice\PhpSpreadsheet\IOFactory;
use think\facade\Filesystem;
use think\facade\Queue;
use think\facade\View;
use app\BaseController;
use think\facade\Db;
class Index
{
//类中的test方法
public function Test()
{
//上传Excel表
$file = request()->file('file');
//保存数据
$savename = [];
//文件保存地址
$savename = Filesystem::putFile('upload', $file, time() . '.xlsx');
//此处为检测表格文件有没有上传成功,也可以去掉这个给if($savename)
if ($savename) {
$filePath = $file->getPathname();
$this->splitDataAndQueue($filePath);
return '文件上传成功,数据处理中...';
}
}
//建立一个私有类用来写获取和导入的方法
//此处我的写法是在控制器中处理数据,然后用chunk函数进行分块
//(为什么要进行分块?你不能把数据全塞进去把,不会吧?不会把?真有人硬塞啊)
//分块为100条的数据组,用job直接插入数据库
//还有种写法是在job里进行处理数据和进行插入,少数据量也能成功,但师傅让我在控制器的进行处理,这样会节约内存,同时更好美观点。此处就不放了
private function splitDataAndQueue( $filePath)
{
//$spreadsheet代表整个spreadsheet文档,用来获取整个spreadsheet文件
$spreadsheet = IOFactory::load($filePath);
//用getActiveSheet方法获得工作表
$worksheet = $spreadsheet->getActiveSheet();
//设立一个$map,map是PHP中的一个关联数组,它可以将一个键和一个值关联起来。使用PHP中的map可以非常方便地操作数据,此处用法为关联数据库的数据标签名称,让数据一对一入库
$map = [
'A' => 'logistics_no',
'B' => 'order_id',
'C' => 'package_id',
'D' => 'gmt_create',
'E' => 'gmt_send',
'F' => 'gmt_cancel',
'G' => 'country',
'H' => 'alias',
'I' => 'name',
'J' => 'housename',
'K' => 'sys_agent_order_id'
];
//设立一个空数组$data
$data = [];
//遍历工作表的所有“行”数据,getRowlterator为PHPoffice种的行迭代器方法
foreach ($worksheet->getRowIterator() as $a=>$row)
{
//如果$a=1,则继续执行,此处不慌,在下面有解析为什么设立,写到一块方便大家看
if($a==1){
continue;
}
//建立个新的空数组
$rowData = [];
//行完了当然是列遍历有列,$index获取数组索引
foreach ($row->getCellIterator() as $index => $cell) {
//获取单元格坐标
$Coordinate = $cell->getParent()->getCurrentCoordinate();
//$POS字母部分在$map数组中查找对应的字段名,并将结果保存到$field变量中。
$POS = substr($Coordinate, 0, 1);
//$field去对应map的值
$field = $map[$POS];
//这边是从$index开始,去获取单元格的值,因为data[0]是你的表头定义,从$data[1]开始才是你要填入 的数据
$rowData[$map[$index]] = $cell->getValue()
}
$data[] = $rowData;
}
dump($data);
//下免得注释为删除$data[0],此方法不太好用
// unset ($data[0]);
$arr=[];
//对$data进行分割,我是拆分为了100条1次上传给job插入,每次传递给job100条信息用于提高效率,同时降低redis的
//存储,redis最大存储是150kb,这块可能用词不当希望了解的评论区说明,后面后改
$chunks = array_chunk($data, 100);
//$push提交给job
foreach ($chunks as $chunk) {
//下面$chunk本来是按照文档来想用['data]=>$chunk来着,queue文档在job用的是$data,
//但我这里试了,报错为job里找不到$data,索性后面也直接用的$chunk。可以修改
$push = Queue::push('app\job\job1', $chunk);
dump($push);
echo '任务以提交,稍后将处理Excel文件';
}
}
//视图层会用就行
public function index()
{
return View::fetch('index');
}
3.job类代码
在这里插入代码片
<?php
namespace app\job;
use think\queue\Job;
use think\facade\Db;
//发布的任务,数据库批量上传任务
class Job1
{
public function fire(Job $job,$chunk)
{
Db::name('come ')->insertAll($chunk);
//唯一注意的就是insetALLl了,insetALL在tp6为插入多维数组,此处用的$chunk 已在上面说明原因
echo '上传成功';
$job->delete();
}
public function failed($chunk){
$delay=5;
$chunk->release($delay);
echo '导入失败';
}
}
4.视图代码
在这里插入代码片<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>传输文件</title>
</head>
<body>
<form action="/Index.php/Index/test" method="post" enctype="multipart/form-data"><!--路由名称搞明白-->
<input type="file" name="file" id="file" /><!--file提交到本地-->
<input type="submit" name="file" value="上传文件" />
</form>
</body>
</html>
5.文件格式截图
采用的单应用,多应用还没测,但应该也能成功
6.上传成功截图,没有前面上传成功字段的都是失败,去runtime查询失败原因,也可以评论区留言
在这里插入图片描述
三、总结
难点在于对数据的遍历方式,数组遍历完成后job不认可这种方式导致报错,数组下标为空就是没找到数据