做数据导出时经常会出现数据量太大导致最后程序卡死 反正我写不来 公司好同事我辈学习之榜样曹老板写的 我给偷过来啦
<?php class ExportCsv { private $path = ''; private $header = []; private $db = null; private $fp = null; private $total = 0; private $writeRow = 0; private $time ; function __construct($file) { $this->time = time(); set_time_limit(0); $endtitle = local_date("Y-m-d-h-i-s"); $this->path = "{$file}-{$endtitle}.xls"; $this->db = &m('store'); header('Content-Type:text/html;charset=utf-8'); header("Content-Encoding: none\r\n"); ob_implicit_flush(true); } public function setHeader($header) { $this->header = $header; } public function processCsv1($config, $datafunc) { //输出文件头 $this->fp = fopen( ROOT_PATH . '/temp/' .$this->path, 'w'); //echo ROOT_PATH . '/temp/' .$this->path.'<br>'; //echo $this->fp; //exit; if (!empty($this->header)) { $content = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'; $content .= '<table border="1">'; $content .= '<tr>'; foreach ($this->header as $v) { $content .= '<th>' . $v . '</th>'; } $content .= '</tr>'; fwrite($this->fp, $content); } $where = ''; if(isset($config['where']) && !empty($config['where'])) { $where = 'where '.$config['where']; } $countSql = 'select count(DISTINCT('.$config['countfield'].')) from '.$config['from'].' ' . $where; $this->total = $this->db->getOne($countSql); echo '总共'.$this->total.'条记录<br>'; if($this->total > 0) { $pagecount = 2000; $opage = 0; for($pos = 0; $pos<$this->total; $pos+=$pagecount,++$opage) { $selectSql = 'select ' . $config['fields'] . ' from '.$config['from'].' ' . $where . ' '.$config['group']; $selectSql .= " limit " . ($opage) * $pagecount . ", $pagecount"; $this->save2file($selectSql, $datafunc); } } } private function save2file($sql, $datafunc) { $arr = &$this->db->getAll($sql); foreach ($arr as $key => $value) { $value = $datafunc($value); if(empty($value)) { continue; } $content = '<tr>'; foreach ($this->header as $k => $v2) { $tmp = isset($value[$k]) ? $value[$k] : ''; if (is_numeric($tmp)) { $tmp == 0 && $tmp = ''; } $content .= '<td>' . $tmp . '</td>'; } $content .= '</tr>'; fwrite($this->fp, $content); //fputcsv($this->fp, $datafunc($value)); } $this->writeRow += count($arr); unset($arr); echo str_repeat(' ',1024*64); echo '已经读取'.$this->writeRow.'条记录<br>'; ob_flush(); flush(); } public function exportCsv() { if($this->total <= 0) { echo '没有可导出数据<br>'; return; } fwrite($this->fp, '</table>'); fclose($this->fp); echo '读取完毕<br>'; echo '耗时:' . intval(time()-($this->time)).'秒<br>'; echo '<a href="'.STATIC_URL . '/export/' . $this->path .'" download="'.$this->path.'">点击下载</a>'; exit; } public function exportCsv1() { if($this->total <= 0) { echo '没有可导出数据<br>'; return; } fwrite($this->fp, '</table>'); fclose($this->fp); echo '读取完毕<br>'; echo '耗时:' . intval(time()-($this->time)).'秒<br>'; echo '<a href="'.DOMAIN . '/temp/' .$this->path .'" download="'.$this->path.'">点击下载</a>'; exit; } }
使用方法
if(isset($_GET['excel'])) { $export = new ExportCsv('userview'); $export->setHeader([ "type" => "类型", "title" => "名称", "user_name" => "用户", "store_name" => "店铺", "user_type" => "用户类型", "add_time" => "浏览时间", "referer" => "来源页面" ]); $config = []; $config['countfield'] = 'member_visitor.id'; $config['fields'] = 'member_visitor.*,member_visitor.types as vtypes,m.user_name,m.isbazaar,uv.store_id as priv_store_id,uv.privs,s.store_id'; $config['from'] = 'eihoo_member_visitor as member_visitor lEFT JOIN eihoo_member m ON m.user_id=member_visitor.user_id LEFT JOIN eihoo_user_priv uv on uv.user_id=m.user_id LEFT JOIN eihoo_store s on s.user_id=m.user_id'; //echo $conditions;exit; $config['where'] = '';//筛选条件 $config['group'] = 'group by member_visitor.id'; $export->processCsv1($config, function ($goods) { // 这里返回的是1条数据 大部分情况下要针对这条数据做处理得到用户想要的数据 return $goods; }); $export->exportCsv1(); }