<?php namespace app\api\service; use app\api\model\OrderProduct; use app\api\model\Product; use app\api\model\UserAddress; use app\lib\exception\OrderException; use app\lib\exception\UserException; use think\Exception; class Order { // 订单的商品列表,客户端传递来的下单商品参数--二维数组 protected $oProducts; // 根据product_id从数据库中查询出的真实商品信息--库存量 protected $products; protected $uid; // 下单方法,参数$uid--用户,$oProducts public function place($uid, $oProducts) { // 将传进来的$uid和$oProducts赋值给成员变量$uid和$oProducts $this->uid = $uid; $this->oProducts = $oProducts; // 从数据库中获取$products的信息,调用方法getProductsByOrder $this->products = $this->getProductsByOrder($oProducts); // 获取getOrderStatus方法的返回结果 $status = $this->getOrderStatus(); // 查看库存量是否通过,未通过则: if (!$status['pass']) { //在$status数组中增加订单编号为-1,表示订单创建失败值,作为标记 $status['order_id'] = -1; //返回结果到客户端, return $status; } // 库存量通过,则创建订单.第一步,创建订单快照 $orderSnap = $this->snapOrder($status); $order = $this->createOrder($orderSnap); $order['pass'] = true; return $order; } // 10-12 // 第二步,创建订单 private function createOrder($snap) { try { // 订单号 $orderNo = $this->makeOrderNo(); // 实例化order模型 $order = new \app\api\model\Order(); // 数据库的order表中插入数据 $order->user_id = $this->uid; $order->order_no = $orderNo; $order->total_price = $snap['orderPrice']; $order->total_count = $snap['totalCount']; $order->snap_img = $snap['snapImg']; $order->snap_name = $snap['snapNme']; $order->snap_address = $snap['snapAddress']; $order->snap_items = json_encode($snap['pStatus']); $order->save(); // order表的id 插入 到order_product的order_id赋值 // 获取order表的id和create_time $orderID = $order->id; $create_time = $order->create_time; // 为订单中的每一个商品添加$orderID // &引用符号,才能够在数组中增加字段 foreach ($this->oProducts as &$p) { $p['order_id'] = $orderID; } //调用模型orderproduct,将数据保存到数据库order_product表 $orderProduct = new OrderProduct(); // 保存数组需要调用saveAll方法 $orderProduct->saveAll($this->oProducts); return [ 'order_no' => $orderNo, 'order_id' => $orderID, 'create_time' => $create_time ]; } catch (Exception $ex) { throw $ex; } } // 生成订单号 public static function makeOrderNo() { $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'); $orderSn = $yCode[intval(date('Y')) - 2019] . strtoupper(dechex(date('m'))) . date( 'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf( '%02d', rand(0, 99)); return $orderSn; } // 10-11 // 生成订单快照 private function snapOrder($status) { //快照信息的关联数组 $snap = [ //商品总价 'orderPrice' => 0, //所有商品的数量和 'totalCount' => 0, //单类商品的详细信息 'pStatus' => [], //快照地址,快照商品名,快照商品图 'snapAddress' => null, //订单中第一个商品的名字和图片作为快照 'snapName' => '', 'snapImg' => '' ]; $snap['orderPrice'] = $status['orderPrice']; $snap['totalCount'] = $status['totalCount']; $snap['pStatus'] = $status['pStatusArray']; //将$userAddress数组序列化为json字符串,方便存入数据库中,但不太好. $snap['snapAddress'] = json_encode($this->getUserAddress()); $snap['snapName'] = $this->products[0]['name']; $snap['snapImg'] = $this->products[0]['main_img_url']; if (count($this->products) > 1) { $snap['snapName'] .= '等'; } // print_r($snap); } // 获取快照地址 private function getUserAddress() { //获取$userAddress对象 $userAddress = UserAddress::where('user_id', '=', $this->uid)->find(); if (!$userAddress) { throw new UserException([ 'msg' => '用户收货地址不存在,下单失败', 'errorCode' => 60001 ]); } //返回$userAddress数组 return $userAddress->toArray(); } // 10-9 下单接口业务模型二 // 定义方法:获取订单状态.对比$oProducts和$products,检验库存量 // 此处不需要传递参数$oProducts和$products,是因为本类中已经定了赋值好了. // 定义订单状态相关属性,用于返回结果 // pass--库存量检测是否通过,默认值设为true // orderPrice--所有商品价格总和,默认值设为0 // pStatusArray--数组,通过order的product_id获取并保存订单中所有商品的详细信息 // 用于历史订单,默认值设为空数组 //获取订单状态,返回值为数组,包含库存量是否充足,所有商品总价,和所有订单商品的详细信息. private function getOrderStatus() { $status = [ 'pass' => true, 'orderPrice' => 0, 'totalCount' => 0, 'pStatusArray' => [] ]; // 使用循环对比进行库存量检测 foreach ($this->oProducts as $oProduct) { $pStatus = $this->getProductStatus( $oProduct['product_id'], $oProduct['count'], $this->products ); if (!$pStatus['haveStock']) { $status['pass'] = false; } $status['orderPrice'] += $pStatus['totalPrice']; $status['totalCount'] += $pStatus['count']; array_push($status['pStatusArray'], $pStatus); } return $status; } // 定义方法getProductStatus // 根据$oPIDs中的product_id获取$products数组中对应的商品库存量 // $oPIDs数组中只有product_id // 定义$pStatus的数据结构 // $pStatus的作用,将本次订单信息保存至历史订单 // $pIndex指定product_id在$products中id对应数组的下标序号 // totalPrice--订单中某个商品的总价格 private function getProductStatus($oPIDs, $oCount, $products) { $pIndex = -1; $pStatus = [ 'id' => null, 'haveStock' => false, //订单中某个商品的数量 'count' => 0, 'name' => '', 'totalPrice' => 0 ]; //使用循环找出$pIndex for ($i = 0; $i < count($products); $i++) { if ($oPIDs == $products[$i]['id']) { $pIndex = $i; } } if ($pIndex == -1) { //以防用户下单的商品客户端传递的productid有可能根本不存在,在服务器中已经下架了或丢失了,即$pIndex = -1,需要抛出异常 throw new OrderException([ 'msg' => 'id为' . $oPIDs . '的商品不存在,订单创建失败' ]); } else { $products = $products[$pIndex]; $pStatus['id'] = $products['id']; $pStatus['count'] = $oCount; $pStatus['name'] = $products['name']; $pStatus['totalPrice'] = $products['price'] * $oCount; if ($products['stock'] - $oCount >= 0) { $pStatus['haveStock'] = true; } } return $pStatus; } // 根据订单信息$oProducts查找真实的商品信息$products private function getProductsByOrder($oProducts) { // 通过循环将product_id读取出来并存放在$oPIDs数组中,$oPIDs是一个只有product_id的以为数组. $oPIDs = []; foreach ($oProducts as $item) { array_push($oPIDs, $item['product_id']); } // 通过新构造的数组$oPIDs,调用Product模型的all方法到数据库中进行硬查询 // 并使用->visible方法获取指定部分数据 // 之前在全局配置中数组返回形式是collection数据集, // 此处使用数据集的toArray方法将数据集转化为数组形式(方便与$oProducts数组作对比) // 查询结构$products是一个二维数组 $products = Product::all($oPIDs) ->visible(['id', 'price', 'stock', 'name', 'main_img_url']) ->toArray(); return $products; } }
慕斯4360584
慕斯4360584
慕设计2395807