WithCoderWithCoderWithCoder

Think PHP5框架中实现PHP导出大数据到CSV文件

    在使用php实现excel表格导出功能时,当导出少量数据还好,一旦数据量级达到5w、10w、20w甚至30以上的时候就会面临这样的问题:

    1. 导出时间变得很慢,少则1分钟,多则好几分钟,数据量一旦上来,还可能面临导不出来的情况(这种导出效率正常人都会受不了,更何况是要求苛刻的用户)。

    2. 导出消耗大量的内存资源,即使把php内存使用设置为无限大,当多个用户同时使用导出功能导出大量数据的时候,服务器内存使用就会直线往上升,报警,甚至宕机,严重影响其他业务。

    因为上面的问题,考虑将数据导出到CSV文件,这样导出的文件不仅小,而且兼容性比较好,可以使用文本文档、word、Excel等多种方式打开。本文简单介绍将数据导出到CSV的实现过程,暂不牵涉大数据处理。

    准备

    1. 开发环境Think PHP5

    2. 数据准备为家庭/成员主子表

    导出效果图

    用Excel打开:

    1-20042116195S34.png

    用word打开:

    1-20042116214M50.png

    导出

    1. 准备数据

    创建两个数据表,家庭表(tn_home):

CREATE TABLE `tn_home` (
  `home_id` int(11) NOT NULL COMMENT '家庭id',
  `home_name` varchar(50) DEFAULT NULL COMMENT '家庭名',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`home_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

    成员表(tn_home_member):

CREATE TABLE `tn_home_member` (
  `member_id` int(11) NOT NULL COMMENT '家庭成员id',
  `home_id` int(11) DEFAULT NULL COMMENT '家庭id',
  `member_name` varchar(50) DEFAULT NULL COMMENT '成员名',
  PRIMARY KEY (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

    2. 在tp5中,连接数据库,生成导出的数据结构。PHP代码如下:

function export()
{
    // 生成数据结构(tp5用Db返回数组)
    // 家庭成员表数据(主子表连接)
    $home = Db::table('tn_home_member')
        ->alias('a')
        ->field('b.home_id,b.home_name,a.member_name,b.create_time')
        ->join('tn_home b', ' a.home_id = b.home_id', 'left')
        ->select();

    // 生成表头
    $cells = array(
        array('home_id', '家庭id'),
        array('home_name', '家庭名'),
        array('member_name', '成员姓名'),
        array('create_time', '创建时间'),
    );

    // 导出csv
    $this->exportCSV('家庭成员表', $cells, $home);
}

    3. 调用导出方法,生成CSV并输出到页面:   

public function exportCSV($fileName, $cells, $datas)
{
   set_time_limit(0);
   ini_set('memory_limit', '1024M'); //设置程序运行的内存
   ini_set('max_execution_time', 0); //设置程序的执行时间,0为无上限
   ob_end_clean();  //清除内存
   ob_start();

   header('Content-Type: application/vnd.ms-excel');   // header设置
   header("Content-Disposition: attachment;filename=" . $fileName . ".csv");
   header('Cache-Control: max-age=0');

   //打开php文件句柄,php://output表示直接输出到PHP缓存,a表示将输出的内容追加到文件末尾
   $fp = fopen('php://output', 'a');

   // 表头信息
   foreach ($cells as $cell) {
       //utf-8编码转为gbk。理由是: Excel ANSI 格式打开,不会做编码识别。如果直接用 Excel 打开 UTF-8 编码的 CSV 文件会导致汉字部分出现乱码。
       $head[] = iconv("UTF-8", "GBK//IGNORE", $cell[1]);
   }
   // fputcsv() 函数将行格式$head化为 CSV 并写入一个打开的文件$fp
   fputcsv($fp, $head);

   if ($datas) {
       foreach ($datas as $data) {
           $cessData = [];  //要导出的数据的顺序与表头一致
           foreach ($cells as $cell) {
               $cessData[] = iconv("UTF-8", "GBK//IGNORE", $data[$cell[0]]);
           }
           fputcsv($fp, $cessData);
       }
       ob_flush();//清除内存
       flush();
   }

   ob_end_clean();
   exit;  //记得加这个,不然会跳转到某个页面。
}

    通过以上代码,会将数据保存到CSV文件,并输出到页面。

欢迎分享交流,转载请注明出处:WithCoder » Think PHP5框架中实现PHP导出大数据到CSV文件