php实现导出10万条数据

开发中经常遇到需要从数据库导出大量数据的问题,导出excel需要占用太多内存,最终回导致内存溢出而失败。csv是更好的选择。同时可以使用php5.5之后赋予的新功能——yield(生成器)来优化性能,具体可以看鸟哥博客http://www.laruence.com/tag/yield

/**
     * 分段导出所有用户
     */
    public function exportAll()
    {
        set_time_limit(0);
        $count = D('user')->count();
        $num = 0;
        $f = null;
        foreach ($this->getCounts($count,function($fp) use (&$f){
            $f = $fp;
        }) as $value) {
            $num++;
            if (1000 === $num) {
                ob_flush();
                flush();
                $num = 0;
            }
            foreach ($value as $v) {
                fputcsv($f,$v);
            }
            
            fclose($f);
        }
        //导出合并后的文件
        $this->mergeFile(function($file){
            error_reporting(0);
            header("Cache-Control: max-age=0");
            header("Content-Description: File Transfer");
            header('Content-disposition: attachment; filename=songdaozong.csv'); // 文件名
            header("Content-Type: application/csv"); 
            header("Content-Transfer-Encoding: binary"); 
            header('Content-Length: ' . filesize($file));
            readfile($file);//输出文件;
            self::clearFile();
        });
    }
/**
     * 获取阶段导出数据
     */
    private function getCounts($count,$handle)
    {
        $pageCount = ceil($count/1000);
        for ($i=0; $i < $pageCount; $i++) { 
            $file = __DIR__ . '/_' . $i . '.csv';
            touch($file);
            $fp = fopen($file, 'w'); //生成临时文件
            if ($handle instanceof \closure) {
                $handle($fp);
            }
            yield D('user')->limit($i*1000,1000)->select();
        }
    }

    /** 
     * 处理数组格式
     */
    private static function makeArray(array $data)
    {
        $new = [];
        foreach ($data as $key => $value) {
            $new[] = array_values($value);
        }

        return $new;
    }

    /**
     * 合并文件
     */
    private function mergeFile($handle)
    {
        $fileList = glob(__DIR__.'/*.csv');
        $count = count($fileList);
        for ($i=0; $i < $count; $i++) { 
            if ($i > 0) {
                file_put_contents($fileList[0],file_get_contents($fileList[$i]),FILE_APPEND);
            }
        }
        if ($handle instanceof \closure) {
            $handle($fileList[0]);
        }
    }

    /** 
     * 清除文件
     */
    private static function clearFile()
    {
        error_reporting(0);
        $fileList = glob(__DIR__.'/*.csv');
        foreach ($fileList as $value) {
            unlink($value);
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容