php导出mysql数据表到excel实现(千万级别数据-以自己以前做的订单导出为demo给大家参考)

考虑几个重点:

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');
    }

}

猜你喜欢

转载自blog.csdn.net/Baron0071/article/details/83214088