这时就须要循环批量写入excle导出

过程中可能碰着的问题:

1.超时:Maximum execution time of 30 seconds exceeded

php获取十万数据PHPexcle年夜数据量导出 GraphQL

办理:在文件开头加上 set_time_limit(0);即php实行韶光不受限定。

2.内存溢出:Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)

办理:

2.1 可在ini文件设置;设置memory_limit,将内存设置加大,

2.2 在实行代码前加上 ini_set(\公众memory_limit\"大众, \公众1024M\公众);

2.3 每次读取的数据量减少,增加循环的次数;

3.导出的excle数字过长展示成科学计数

办理:

3.1 在要写入的数字数据,后面加个 “\t”;

3.2 或是数字转换为字符串格式

上代码(天生excle链接导出数据):

​public function downBigExcle()

​ ​ ​{

​ ​ ​ set_time_limit(0);

​ ​ ​ #自定义导出地址+文件名

​ ​ ​

​ ​ ​ $pathName = time().'.csv';

​ ​ ​

​ ​ ​ #打算要导出总数据条数

​ ​ ​

​ ​ ​ $totalNums = Db::table('t_excle')->count('id');

​ ​ ​

​ ​ ​ #设置表头标题

​ ​ ​

​ ​ ​ $headerTitleArr = ['xx','xxx'];

​ ​ ​

​ ​ ​ #CSV的Excel支持GBK编码,一定要转换,否则乱码

​ ​ ​

​ ​ ​ foreach ($headerTitleArr as $i => $v) {

​ ​ ​

​ ​ ​ $headerTitleArr[$i] = iconv('utf-8', 'gbk', $v);

​ ​ ​

​ ​ ​ }

​ ​ ​

​ ​ ​ #每次查询的条数

​ ​ ​

​ ​ ​ $pageSize = 5000;

​ ​ ​

​ ​ ​ #分批导的次数

​ ​ ​

​ ​ ​ $pages = ceil($totalNums / $pageSize);

​ ​ ​

​ ​ ​ #打开文件流

​ ​ ​

​ ​ ​ $fp = fopen($pathName, 'a');

​ ​ ​

​ ​ ​ #将数据格式化为CSV格式并写入到文件流中

​ ​ ​

​ ​ ​ fputcsv($fp, $headerTitleArr);

​ ​ ​

​ ​ ​ #主体内容

​ ​ ​

​ ​ ​ $paegNum = 0;

​ ​ ​

​ ​ ​ for ($i=0; $i <$pages ; $i++) {

​ ​ ​

​ ​ ​ $data = Db::table('t_excle')->limit($paegNum,$pageSize)->field('')->select();

​ ​ ​

​ ​ ​ foreach ($data as $fields) {

​ ​ ​

​ ​ ​ foreach ($fields as $key => &$v) {

​ ​ ​

​ ​ ​ // CSV的Excel支持GBK编码,一定要转换,否则乱码

​ ​ ​

​ ​ ​ // 加\"大众\t\"大众防止数字导出时变成科学计数

​ ​ ​

​ ​ ​ $v = iconv('utf-8', 'gbk', $v.\"大众\t\"大众);

​ ​ ​

​ ​ ​ }

​ ​ ​

​ ​ ​ fputcsv($fp, $fields);

​ ​ ​

​ ​ ​ //这边可记录下数据的末了一次的位置,便于查看排错定位。

​ ​ ​

​ ​ ​ }

​ ​ ​

​ ​ ​ unset($data);//开释变量的内存

​ ​ ​

​ ​ ​ $paegNum += $pageSize;

​ ​ ​

​ ​ ​ }

​ ​ ​

​ ​ ​ fclose($fp);

​ ​ ​

​ ​ ​ #输出下载链接,url为下载的域名

​ ​ ​

​ ​ ​ return $url.$pathName;

​ ​ ​

​ ​ ​ }

对付一个要求来说PHP是单线程的,大数据量的导出又是最耗时的,搞不好其他要求就壅塞了。

小数据量的话,可以直接浏览器输出;

大数据量的话,可以天生excle下载链接;推举利用swoole异步框架处理要求。

1.当客服在后台系统点击下载后,可先返回个提示或是天生一条下载记录;

2.在后台异步处理excle导出操作;

3.客服主动刷新页面查看是否有下载链接天生。

再上代码(天生excle直接浏览器输出):

​ ​ public function downOrderData($timeStart, $timeEnd)

​ ​

​ ​{

​ ​

​ ​ set_time_limit(0);

​ ​

​ ​ $columns = [

​ ​

​ ​ '序号ID', '姓名', '电话', ......

​ ​

​ ​ ];

​ ​

​ ​ $csvFileName = '订单数据' . $timeStart .'_'. $timeEnd . '.xlsx';

​ ​

​ ​ //设置好见告浏览器要下载excel文件的headers

​ ​

​ ​ header('Content-Description: File Transfer');

​ ​

​ ​ header('Content-Type: application/vnd.ms-excel');

​ ​

​ ​ header('Content-Disposition: attachment; filename=\"大众'. $fileName .'\公众');

​ ​

​ ​ header('Expires: 0');

​ ​

​ ​ header('Cache-Control: must-revalidate');

​ ​

​ ​ header('Pragma: public');

​ ​

​ ​ $fp = fopen('php://output', 'a');//打开output流

​ ​

​ ​ mb_convert_variables('GBK', 'UTF-8', $columns);

​ ​

​ ​ fputcsv($fp, $columns);//将数据格式化为CSV格式并写入到output流中

​ ​

​ ​ $accessNum = '100000'//从数据库获取总量,假设是十万

​ ​

​ ​ $perSize = 1000;//每次查询的条数

​ ​

​ ​ $pages = ceil($accessNum / $perSize);

​ ​

​ ​ $lastId = 0;

​ ​

​ ​ for($i = 1; $i <= $pages; $i++) {

​ ​

​ ​ $data = Db::table('t_excle')->limit($lastId ,$pageSize)->field('')->select();

​ ​

​ ​ foreach($data as $value) {

​ ​

​ ​ mb_convert_variables('GBK', 'UTF-8', $value);

​ ​

​ ​ fputcsv($fp, $value);

​ ​

​ ​ $lastId = $value['id'];

​ ​

​ ​ }

​ ​

​ ​ unset($data);//开释变量的内存

​ ​

​ ​ //刷新输出缓冲到浏览器

​ ​

​ ​ ob_flush();

​ ​

​ ​ flush();//必须同时利用 ob_flush() 和flush() 函数来刷新输出缓冲。

​ ​

​ ​ }

​ ​

​ ​ fclose($fp);

​ ​

​ ​ exit();

​ ​

​ ​}

PS:更多信息互换,请关照:倒影Amoy

活着便是为了改变天下,难道还有其他缘故原由吗?----乔布斯

请输入图片描述