工作中,有时候客户需要导出数据库表数据,当数据量较大时,可以使用下面方法实现。
如果发现有错误之处或者更好的解决方案,欢迎您的留言!
<!--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;
}