公司运营的商城系统是基于萤火商城二开的。其中批量发货功能由之前的程序员开发发,在发送数量,和性能都存在很大的问题。抽出时间来对该功能进行梳理。首先展示下发货的模板,
基本思路整理:上传csv文件 ->获取csv文件内容 -> 获取订单号验证是否存在 -> 更新订单商品表发货状态 -> 更新订单表发货状态(这里注意一个订单对应多个商品时的发货状态处理)
第一步:获取.csv文件方法:
private function getCsvData()
{
// 获取表单上传文件 例如上传了001.jpg
if (!$file = \request()->file('iFile')) {
$this->error = '请上传发货模板';
return false;
}
// 设置区域信息
setlocale(LC_ALL, 'zh_CN');
// 打开上传的文件
$csvFile = fopen($file->getInfo()['tmp_name'], 'r');
// 忽略第一行(csv标题)
fgetcsv($csvFile);
// 遍历并记录订单信息
$orderList = [];
$msg = '模板文件数据不合法';
while ($item = fgetcsv($csvFile)) {
if (isset($item[0]) && !empty($item[0]) && isset($item[1]) && !empty($item[1])) {
unset($msg);
}
if(isset($msg)){
fclose($csvFile);
$this->error = $msg;
return false;
}
$orderList[] = $item;
}
if (empty($orderList)) {
fclose($csvFile);
$this->error = '模板文件中没有订单数据';
return false;
}
fclose($csvFile);
return $orderList;
}
第二步到第四步:订单号处理:
public function batchDelivery($data)
{
// 获取csv文件中的数据 if ( (!$csvData = $this->getCsvData() ) || (!$excelData = $this->getExcelData() ) ) {
$csvData = $this->getCsvData() ;
// $csvData 数据过滤 这一步也可以省略
if($csvData && !empty($csvData)){
foreach ($csvData as $k => $value){
if (isset($value[0])){
$csvData[$k][0] =trim(strip_tags(substr($value[0],0)));//注意获取订单号 要去除空格
}
}
} else{
return false;
}
//第三步:获取订单号验证是否存在
// 整理订单要发货的订单order_no集
$orderNos = helper::getArrayColumn($csvData, 0); //整理所有订单号 成为数组
// 获取订单列表数据
$orderList = helper::arrayColumn2Key(($this->getListByOrderNos($orderNos)),'order_no');
// 验证订单是否存在
$tempArr = array_values(array_diff($orderNos, array_keys($orderList)));
if (!empty($tempArr)) {
$this->error = "订单号[{$tempArr[0]}] 不存在!";
return false;
}
// 验证订单是否满足发货条件
if (!$this->verifyDelivery($orderList)) {
return false;
}
// 第四步: 更新订单商品表发货状态(方法在下面)
//根据提供信息更新订单商品表
$this->updateOrderGoods($csvData,$orderList);
//第五步: 更新订单表发货状态
//检查此订单下商品是否有未发货的,如果都已发货更新整个订单的状态
$orderGoods=new OrderGoodsModel(); //实例化订单商品表模型
$orderModel=new OrderModel(); //实例化订单表
$orderGoodsdeliverylist= [];
$updateOrderList=array();
foreach ($csvData as $item) {
$order_id=$orderList[$item[0]]['order_id'];
//更新一个订单多个商品 订单的物流信息
//查询查询订单商品表 该订单下的商品是否全部发货。是更新订单表该订单状态为已发货 否则只更新订单商品表发货状态 //该查询语句还可以优化
$orderGoods20=$orderGoods->where('order_id','=',$order_id)->where('delivery_status','=',20)->field('order_goods_id')->find();
// if ($orderList[$item[0]]['delivery_status']['value'] == 20){
if ($orderGoods20){ //更新订单表订单状态
$orderGoodsdeliverylist[] =array(
'express_id' => $item[3],
'express_no'=>$item[1],
'express_company'=>eval('return '.iconv('gbk','utf-8',var_export($item[4],true)).';'),
'delivery_time'=>time(),
'delivery_status'=>20,
'order_id'=>$order_id
);
}else{ // 多个商品未发货订单只更新订单表物流单号
$updateOrderList[]=array(
'order_id'=>$order_id,
'express_id'=>$item[3],
'express_no'=>$item[1],
'express_company'=>eval('return '.iconv('gbk','utf-8',var_export($item[4],true)).';')
);
}
}
// 更新订单发货状态(批量) updateToDelivery 方法在下面
if ($status = $this->updateToDelivery($updateOrderList)){
//更新更新一个订单多个商品 类订单 已发过货的订单状态
$deliverystatus= $orderModel->isUpdate(false)->saveAll($orderGoodsdeliverylist);
// 获取已发货的订单
$completed = $this->getListByOrderNos($orderNos, ['user', 'address', 'goods', 'express']);
// 发送消息通知
$this->sendDeliveryMessage($completed);
// 同步好物圈订单
(new WowService(self::$wxapp_id))->update($completed);
}
return $status;
}
// 第四步:
/**
* 更新订单商品的发货数据信息,一个订单存在多个商品
* @param $data array
* @return bool
*/
public function updateOrderGoods($data=array(),$orderList=array()){
if(!isset($data)){return false;}
$goodsOrder=array();
$orderGoods=new OrderGoodsModel();
//更新订单商品表
foreach($data as $k => $v){
if (!empty($v[0])){
$goodsOrder[$k]['order_goods_id']=trim($v[2]);
$goodsOrder[$k]['delivery_status']=20;
$goodsOrder[$k]['delivery_no']=$v[1];
$goodsOrder[$k]['delivery_id']=$v[3];
$goodsOrder[$k]['delivery_time']=time();
$goodsOrder[$k]['delivery_name']=eval('return '.iconv('gbk','utf-8',var_export($v[4],true)).';');
}
}
$orderGoods->saveAll($goodsOrder);
}
/**
* 更新订单发货状态(批量)
* @param $orderList
* @return array|false
* @throws \Exception
*/
private function updateToDelivery($orderList)
{
if(!isset($orderList)){return false;}
$data = [];
foreach ($orderList as $item) {
$data[] = [
'order_id' => $item['order_id'],
'express_no' => $item['express_no'],
'express_id' => $item['express_id'],
'delivery_status' => 20,
'delivery_time' => time(),
];
}
return $this->isUpdate()->saveAll($data);
}
以上就是订单批量发货的全部方法。该方法是在tp5 框架中使用的。主要方法都贴出来了,有些调用模型查数据的方法都是常用的,没有贴出。之所以记录,是因为之前的技术在这个方法中饶了很多弯,在每一次更新数据前都调用数据库查询方法链接数据库,导致批量发货的数量和稳定性都很差。我花了好几天的功夫才把他写的代码吃透,把这个方法优化处理了下。 特在此简单记录,以备以后用到。 供网友们借鉴。