1.使用插件的方式
https://docs.laravel-excel.com/3.1/imports/batch-inserts.html
1.安装插件
composer require maatwebsite/excel
2.创建一个操作导出表的类
php artisan make:export UsersExport 在app/Exports文件夹中生成UsersExport.php
<?php namespace AppExports; use MaatwebsiteExcelConcernsFromCollection; use MaatwebsiteExcelConcernsWithMapping; use MaatwebsiteExcelConcernsWithHeadings; class SellExport implements FromCollection, WithMapping, WithHeadings { public function __construct(){ //传参数时可以在构造函数中初始化 } /** * @return IlluminateSupportCollection */ public function collection() { //跨数据库操作表 $db = DB::connection('old_mysql'); $result = $db->table('student as s')->select([ DB::raw("sum(s.score) as total"), 's.number', 's.name', 'g.phone', ])->leftJoin('gift as g', 'g.sid', '=', 's.gid') ->groupBy('s.number') ->orderBy('total')->get(); return $result; //同时也可以用模型操作比如:return User::all(); } //生成excel表的字段名 public function headings(): array { return [ 'total', 'sales', 'goods_code', 'goods_barcode', 'store_code', 'date', 'cn_name', 'retail_price', 'cost_price', 'package_qty', 'price', ]; } //返回每个字段的值,$sell是collection中return 后遍历的值 public function map($sell): array { return [ $sell->total, $sell->sales, is_numeric($sell->goods_code) ? $sell->goods_code . " " : $sell->goods_code, is_numeric($sell->goods_barcode) ? $sell->goods_barcode . " " : $sell->goods_barcode, $sell->store_code, $sell->date, $sell->cn_name, $sell->retail_price, $sell->cost_price, $sell->package_qty, $sell->price, ]; } } //这里只是一个例子,其它的操作可以查看文档
在控制器中调用下载
use MaatwebsiteExcelFacadesExcel;
$file = 'public/sell/'.$year.'-'.$month.'.xlsx';//默认是根目录下的storage/app
Excel::store(new SellExport(), $file);//store有多个参数,详细可以子在文档中找
2.使用php的csv方式,结合php生成器(yield),减少内存的占用,(生成csv文件后,可以在桌面保存为excel文件),原生操作数据库
private function generateCsv(){ $file = storage_path().'/app/public/sell/'.date('Y-m',strtotime('-1 month')).'.csv'; //生成的csv文件路径
//链接数据库参数 $url='localhost';//主机 $username='root';//用户名 $pwd='root';//用户密码 $database='database_name';//数据库名 $charset='utf8';//字符集 $name='user';//数据表名 $fp = fopen($file, 'a+');//存在打开文件资源,不存在就创建(追加方式)
//csv文件内容头部 $csv_header = ['id','name','age']; fputcsv($fp,$csv_header);//使用fputcsv写入csv文件 foreach($this->select($url,$username,$pwd,$database,$charset,$name) as $value){ fputcsv($fp,$value);//使用yield每次获取一条数据写入到csv文件 } fclose($fp); } private function select($url='',$username='',$pwd='',$database='',$charset='',$name=''){ $link = mysqli_connect($url,$username,$pwd); if(mysqli_connect_errno($link)>0){ die(mysqli_connect_error($link)); } mysqli_set_charset($link,$charset); mysqli_select_db($link,$database); $sql = "select id,name,age from user";$res = mysqli_query($link,trim($sql));//成功返回true否则false
//mysqli_fetch_assoc($res)逐条获取,每次都是一条关联数组数据
while($result = mysqli_fetch_assoc($res)){
yield $result;
}
mysqli_close($link);
}
3.laravelDB类操作数据库
使用DB类获取数据生成csv //生成指定时间段表数据的csv文件 private function select() { $start_date = date('Y-m', strtotime('-1 month')); $end_date = date('Y-m'); $file = storage_path().'/app/public/sell/'.date('Y-m', strtotime('-1 month')).'.csv'; $fp = fopen($file, 'a+');//打开csv文件,没有就自动创建 $csv_header = ['total','sales','goods_code','goods_barcode','store_code','date','cn_name','retail_price','cost_price','package_qty','price']; fputcsv($fp, $csv_header);//插入字段名
//获取某时间段的所有数据,使用生成器yield返回单条数据 function getData($start_date, $end_date) {
//$dataname是数据库名,也可以在/config/database.php设置 $db = DB::connection($dataname); $result = $db->table('user as s')->select([ DB::raw("sum(s.count) as total"), DB::raw("sum(s.price) as sales"), 's.name', 'p.cn_name', ])->leftJoin('phone as p', 'g.user_id', '=', 's.id') ->where('s.date', '>=', $start_date) ->where('s.date', '<', $end_date) ->groupBy('s.goods_code', 's.store_code', 's.date') ->orderBy('total')->get()->map(function ($item) { return (array)$item;//通过get()获取到的是集合对象,将内存对象通过map返回数组,内层对象就转为数组, }); foreach ($result as $item) {
//如果在csv表中字段值以科学计数法显示加上这个" "
$item['goods_barcode'] = is_numeric($item['goods_barcode']) ? $item['goods_barcode'] . " " : $item['goods_barcode'];
yield $item;//生成器返回的是一维数组 } };
//调用函数,获取生成器的数据,通过遍历获取 foreach (getData($start_date, $end_date) as $data) { fputcsv($fp, $data);//$data要是一维数组才行 } fclose($fp); }