考虑几个重点:
1,服务器承载 2,redis数据缓存避免数据重复导出,3,导出后的数据处理 4,死循环 5,数据大小,限制大变量的出现
遇到这样的需求,大家根据自己的需求去处理业务,多方位去考虑程序的可执行性,性能等多方面因素(尽量减少循环中的查询次数)
不多说附上代码供大家参考
<?php
class ReportOrdersExport extends Job implements SelfHandling, ShouldQueue
{
protected $start;
protected $end;
protected $shops;
protected $email;
protected $shopArr;
protected $productArr;
protected $brandArr;
protected $catArr;
/**
* ReportOrdersExport constructor.
* @param $start
* @param $end
* @param $email
* @param $shops
*/
public function __construct($start, $end, $email, $shops)
{
$this->start = $start;
$this->end = $end;
$this->shops = $shops;
$this->email = $email;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$start = $this->start;
$end = $this->end;
$shops = $this->shops;
$params['start'] = $start;
$params['end'] = $end;
$params['shops'] = [];
$params['email'] = $this->email;
$key = 'report_orders_'.$start.$end.implode('', $shops);
if (0 < count($shops))
$params['shops'] = Shops::whereIn('shop_id', $shops)->lists('shop_code')->toArray();
$file = Cache::get($key);
if ($file)
return $this->sendEmail($params, $file);
$this->setLoading();
//文件名称
$file = sprintf('%s/%s/%s/%s', date('Y'), date('m'), date('d'), time().'.csv');
//根据自己的需求导出对应的数据
$title = "订单号,会员ID,下单时间,订单总额,颜色,尺码,页面价格,一口价,实付金额,商品数量....";
Storage::append($file, iconv('utf-8', 'gb2312', $title));
//死循环(我是以店铺为单位去匹配对应的数据,然后导出)
$step = 100;
for ($k = 0; 1 == 1; $k += $step) {
$model = Orders::where('status', '<>', 'dead')
->where('pay_status', '1')
->where('pay_time', '>=', $start)
->where('pay_time', '<', $end);
if (0 < count($shops))
$model->whereIn('shop_id', $shops);
$model->orderBy('pay_time', 'asc');
$model->skip($k);
$model->take($step);
$rows = $model->get(['order_id', 'final_amount', 'member_id', 'lv_name', 'shop_id',
'createtime', 'received_time', 'payment', 'status', 'tostr', 'source', 'cost_item', 'pmt_order', 'discount',
'pay_time', 'cost_freight', 'pay_status', 'ship_addr', 'ship_name', 'ship_mobile', 'ship_area']);
//表示已经没有数据
if (1 > count($rows))
break;
foreach ($rows as $row) {
$text = $row->order_id.',';
$member = Members::select(['regtime', 'member_lv_id', 'login_account', 'order_num'])->where('member_id', $row->member_id)->first();
$text .= $row->member_id.',';
$text .= ($member ? $member->login_account : '').',';
$text .= ($member ? $member->order_num : '').',';
$text .= ($row->lv_name ? ($member ? $this->getMemberLvName($member->member_lv_id) : '') : '').',';
$text .= ($member ? date('Y-m-d H:i:s', $member->regtime) : '').',';
$text .= ($row->shop_id ? $this->getShopCode($row->shop_id) : '').',';
$text .= date('Y-m-d H:i:s', $row->createtime).',';
$items = OrderItems::where('order_id', $row->order_id)->get(['goods_id', 'product_id', 'bn', 'name', 'g_price', 'price', 'nums']);
//特殊情况下没明细?应该不会出现
if (1 > count($items)) {
Storage::append($file, $text."\n");
}
$i = 0;
foreach ($items as $item) {
if ($i > 0) $text = ',,,,,,,,,,,,,,,,,,,,,';
$product = $this->getProductInfo($item->product_id);
$text .= ($product ? $product->goods_sn : '').',';
$text .= $item->bn.',';
$text .= $item->name.',';
$text .= ($product ? $this->getBrandName($product->brand_id) : '').',';
$text .= ($product ? $this->getCatInfo($product->cat_id)[2] : '').',';
Storage::append($file, iconv('utf-8', 'gb2312//TRANSLIT//IGNOR', str_replace("\n", "", $text)));
$i++;
}
}
}
//同1份文件8小时内不可以重复导出
Cache::put($key, $file, 60 * 8);
$this->removeLoading();
return $this->sendEmail($params, $file);
}
protected function sendEmail($params, $file)
{
return Mail::send('emails.report', $params, function ($message) use ($params, $file) {
$to = [$params['email']];
$message->to($to)->subject('系统邮件::订单数据');
$message->attach(storage_path("app/$file"));
});
}
protected function setLoading()
{
return Cache::put('report_orders_loading', 1, 60 * 24);
}
protected function removeLoading()
{
return Cache::forget('report_orders_loading');
}
}