php导出csv文件(50万级)

560 阅读1分钟
工作中,有时候客户需要导出数据库表数据,当数据量较大时,可以使用下面方法实现。
如果发现有错误之处或者更好的解决方案,欢迎您的留言!
<!--html代码-->
<a href="控制器方法" target="_blank">导出</a>

<!--php代码  在TP5框架内实现-->
//控制器里面的方法
    static function getData($total_page=1, $page_nums=10000)
    {
        
        for($i=0; $i<$total_page; $i++)
        {
            
            $start = $i * $page_nums;
            //此处这样写的目的是为了让子查询出发组合索引
            $sql="SELECT a.*, (select mobile from xcx_members b where b.id=a.parent_id) as tjr_mobile FROM xcx_members a where id>=(select id from xcx_members where v_type=1 order by id asc limit {$start},1) limit {$page_nums}";
            //此处members表需要组合索引 create index v_type_id_index on members(v_type,id);
            //字段v_type tinyint default 0
            $list = Db::query($sql)
            foreach($list as $k=>$v)
            {
                yield [$v['mobile'],$v['realname'],$v['nickname'],$v['avatar']];
            }
            
            unset($list);
            //每1万条数据就刷新缓冲区
            ob_flush();
            flush();
            //sleep(1);
        }
    }
    
    public function index()
    {
        //生成的csv文件名称
        $demo_csv_filename = time().".csv";
        
        //每页查询数量
        $page_nums = 10000;
        
        //总页数
        $count = Db::name("members")->count("id");
        if($count < $page_nums)
        {
            $total_page = 1;
        }
        else
        {
            $total_page = intval($count / $page_nums) + 1;    
        }
        //csv文件存入的路径
        $base_path = CMF_ROOT."public/upload/";
        
        //导入表头
        $title = [
            '手机号','真实姓名','昵称','头像'
        ];
        
        $fp = fopen($base_path.$demo_csv_filename, 'w');
        
        //写入标题
        fputcsv($fp, $title);
        
        fclose($fp);
        
        $fp = fopen($base_path.$demo_csv_filename, 'a');
        
        foreach(self::getData($total_page, $page_nums) as $m=>$n)
        {
            //写入内容
            fputcsv($fp, $n);
        }
        
        fclose($fp);
        
        $download_url = cmf_get_domain()."/upload/".$demo_csv_filename;
        
        echo "<script>document.location.href='{$download_url}'</script>";
        
        die;
    }