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 App\Exports; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithMapping; use Maatwebsite\Excel\Concerns\WithHeadings; class SellExport implements FromCollection, WithMapping, WithHeadings { public function __construct(){ //傳參數時可以在構造函數中初始化 } /** * @return \Illuminate\Support\Collection */ 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 . "\t" : $sell->goods_code, is_numeric($sell->goods_barcode) ? $sell->goods_barcode . "\t" : $sell->goods_barcode, $sell->store_code, $sell->date, $sell->cn_name, $sell->retail_price, $sell->cost_price, $sell->package_qty, $sell->price, ]; } } //這里只是一個例子,其它的操作可以查看文檔
在控制器中調用下載
use Maatwebsite\Excel\Facades\Excel;
$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表中字段值以科學計數法顯示加上這個"\t"
$item['goods_barcode'] = is_numeric($item['goods_barcode']) ?
$item['goods_barcode'] . "\t" : $item['goods_barcode'];
yield $item;//生成器返回的是一維數組 } };
//調用函數,獲取生成器的數據,通過遍歷獲取 foreach (getData($start_date, $end_date) as $data) { fputcsv($fp, $data);//$data要是一維數組才行 } fclose($fp); }