宝塔ThinkPhp6通过excel插入五十万条数据实例

系列文章目录

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

学习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不认可这种方式导致报错,数组下标为空就是没找到数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值