php date 毫秒_swoole+PHP自动取消订单he还原库存
toujun007 2019-06-27 13:18:57
業務場景
一、業務場景:當客戶下單在指定的時間內如果沒有付款,那我們需要將這筆訂單取消掉,比如好的處理方法是運用延時取消,這里我們用到了swoole,運用swoole的異步毫秒定時器不會影響到當前程序的運行,具體參考:https://wiki.swoole.com/wiki/page/319.html
二、說明,order_status為1時代表客戶下單確定,為2時代表客戶已付款,為0時代表訂單已取消(正是swoole來做的),下面的代表我沒有用框架,比較純的PHP代表方便理解和應用
三、舉例說明,庫存表csdn_product_stock產品ID為1的產品庫存數量為20,產品ID為2的庫存數量為40,然后客戶下單一筆產品ID1減10,產品ID2減20,所以庫存表只夠2次下單,例子中10秒后自動還原庫存,如下圖:
正文講解
圖解:1、第一次下完單產品ID1庫存從20減到了10,產品ID2庫存從40減到了20;2、第二次下完單產品ID的庫存為0了,產品ID2的庫存也為0了,3、第三次下單時,程序提示Out of stock;4、過了10秒鐘(每個訂單下單后往后推10秒),客戶兩次下單,由于沒有付款(csdn_order表的order_status為1),產品1和產品2的庫存被還原了(csdn_order表的order_status變為0),客戶又可以繼續下單了
1、所需要sql數據庫表DROP TABLE IF EXISTS `csdn_order`;CREATE TABLE `csdn_order` (`order_id` int(10) unsigned NOT NULL AUTO_INCREMENT,`order_amount` float(10,2) unsigned NOT NULL DEFAULT '0.00',`user_name` varchar(64) CHARACTER SET latin1 NOT NULL DEFAULT '',`order_status` tinyint(2) unsigned NOT NULL DEFAULT '0',`date_created` datetime NOT NULL,PRIMARY KEY (`order_id`)) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;DROP TABLE IF EXISTS `csdn_order_detail`;CREATE TABLE `csdn_order_detail` (`detail_id` int(10) unsigned NOT NULL AUTO_INCREMENT,`order_id` int(10) unsigned NOT NULL,`product_id` int(10) NOT NULL,`product_price` float(10,2) NOT NULL,`product_number` smallint(4) unsigned NOT NULL DEFAULT '0',`date_created` datetime NOT NULL,PRIMARY KEY (`detail_id`),KEY `idx_order_id` (`order_id`)) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;DROP TABLE IF EXISTS `csdn_product_stock`;CREATE TABLE `csdn_product_stock` (`auto_id` int(10) unsigned NOT NULL AUTO_INCREMENT,`product_id` int(10) NOT NULL,`product_stock_number` int(10) unsigned NOT NULL,`date_modified` datetime NOT NULL,PRIMARY KEY (`auto_id`),KEY `idx_product_id` (`product_id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;INSERT INTO `csdn_product_stock` VALUES ('1', '1', '20', '2018-09-13 19:36:19');INSERT INTO `csdn_product_stock` VALUES ('2', '2', '40', '2018-09-13 19:36:19');2、數據庫配置信息:config.php<?php$dbHost = "192.168.0.110";$dbUser = "root";$dbPassword = "123456";$dbName = "test123";?>3、order_submit.php,生成訂單<?phprequire("config.php");try {$pdo = new PDO("mysql:host=" . $dbHost . ";dbname=" . $dbName, $dbUser, $dbPassword, array(PDO::ATTR_PERSISTENT => true));$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);$orderInfo = array('order_amount' => 10.92,'user_name' => 'yusan','order_status' => 1,'date_created' => 'now()','product_lit' => array(0 => array('product_id' => 1,'product_price' => 5.00,'product_number' => 10,'date_created' => 'now()'),1 => array('product_id' => 2,'product_price' => 5.92,'product_number' => 20,'date_created' => 'now()')));try{$pdo->beginTransaction();//開啟事務處理$sql = 'insert into csdn_order (order_amount, user_name, order_status, date_created) values (:orderAmount, :userName, :orderStatus, now())';$stmt = $pdo->prepare($sql);$affectedRows = $stmt->execute(array(':orderAmount' => $orderInfo['order_amount'], ':userName' => $orderInfo['user_name'], ':orderStatus' => $orderInfo['order_status']));$orderId = $pdo->lastInsertId();if(!$affectedRows) {throw new PDOException("Failure to submit order!");}foreach($orderInfo['product_lit'] as $productInfo) {$sqlProductDetail = 'insert into csdn_order_detail (order_id, product_id, product_price, product_number, date_created) values (:orderId, :productId, :productPrice, :productNumber, now())';$stmtProductDetail = $pdo->prepare($sqlProductDetail);$stmtProductDetail->execute(array(':orderId' => $orderId, ':productId' => $productInfo['product_id'], ':productPrice' => $productInfo['product_price'], ':productNumber' => $productInfo['product_number']));$sqlCheck = "select product_stock_number from csdn_product_stock where product_id=:productId";$stmtCheck = $pdo->prepare($sqlCheck);$stmtCheck->execute(array(':productId' => $productInfo['product_id']));$rowCheck = $stmtCheck->fetch(PDO::FETCH_ASSOC);if($rowCheck['product_stock_number'] < $productInfo['product_number']) {throw new PDOException("Out of stock, Failure to submit order!");}$sqlProductStock = 'update csdn_product_stock set product_stock_number=product_stock_number-:productNumber, date_modified=now() where product_id=:productId';$stmtProductStock = $pdo->prepare($sqlProductStock);$stmtProductStock->execute(array(':productNumber' => $productInfo['product_number'], ':productId' => $productInfo['product_id']));$affectedRowsProductStock = $stmtProductStock->rowCount();//庫存沒有正常扣除,失敗,庫存表里的product_stock_number設置了為非負數//如果庫存不足時,sql異常:SQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '(`test`.`csdn_product_stock`.`product_stock_number` - 20)'if($affectedRowsProductStock <= 0) {throw new PDOException("Out of stock, Failure to submit order!");}}echo "Successful, Order Id is:" . $orderId .",Order Amount is:" . $orderInfo['order_amount'] . "。";$pdo->commit();//提交事務//exec("php order_cancel.php -a" . $orderId . " &");pclose(popen('php order_cancel.php -a ' . $orderId . ' &', 'w'));//system("php order_cancel.php -a" . $orderId . " &", $phpResult);//echo $phpResult;}catch(PDOException $e){echo $e->getMessage();$pdo->rollback();}$pdo = null;} catch (PDOException $e) {echo $e->getMessage();}?>4、order_cancel.php,這個方法主要就是做訂單自動取消,并還原庫存的業務處理<?phprequire("config.php");$queryString = getopt('a:');$userParams = array($queryString);appendLog(date("Y-m-d H:i:s") . "t" . $queryString['a'] . "t" . "start");try {$pdo = new PDO("mysql:host=" . $dbHost . ";dbname=" . $dbName, $dbUser, $dbPassword, array(PDO::ATTR_PERSISTENT => true));$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);swoole_timer_after(10000, function ($queryString) {global $queryString, $pdo;try{$pdo->beginTransaction();//開啟事務處理$orderId = $queryString['a'];$sql = "select order_status from csdn_order where order_id=:orderId";$stmt = $pdo->prepare($sql);$stmt->execute(array(':orderId' => $orderId));$row = $stmt->fetch(PDO::FETCH_ASSOC);//$row['order_status'] === "1"代表已下單,但未付款,我們還原庫存只針對未付款的訂單if(isset($row['order_status']) && $row['order_status'] === "1") {$sqlOrderDetail = "select product_id, product_number from csdn_order_detail where order_id=:orderId";$stmtOrderDetail = $pdo->prepare($sqlOrderDetail);$stmtOrderDetail->execute(array(':orderId' => $orderId));while($rowOrderDetail = $stmtOrderDetail->fetch(PDO::FETCH_ASSOC)) {$sqlRestoreStock = "update csdn_product_stock set product_stock_number=product_stock_number + :productNumber, date_modified=now() where product_id=:productId";$stmtRestoreStock = $pdo->prepare($sqlRestoreStock);$stmtRestoreStock->execute(array(':productNumber' => $rowOrderDetail['product_number'], ':productId' => $rowOrderDetail['product_id']));}$sqlRestoreOrder = "update csdn_order set order_status=:orderStatus where order_id=:orderId";$stmtRestoreOrder = $pdo->prepare($sqlRestoreOrder);$stmtRestoreOrder->execute(array(':orderStatus' => 0, ':orderId' => $orderId));}$pdo->commit();//提交事務}catch(PDOException $e){echo $e->getMessage();$pdo->rollback();}$pdo = null;appendLog(date("Y-m-d H:i:s") . "t" . $queryString['a'] . "t" . "endt" . json_encode($queryString));}, $pdo);} catch (PDOException $e) {echo $e->getMessage();}function appendLog($str) {$dir = 'log.txt';$fh = fopen($dir, "a");fwrite($fh, $str . "n");fclose($fh);}?>
總結
以上是生活随笔為你收集整理的php date 毫秒_swoole+PHP自动取消订单he还原库存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python unicodedecode
- 下一篇: 杉德支付php代码实现_php实现小程序