搜索
首页php框架Swoole这次我用swoole实现订单延时,还原库存!

这次我用swoole实现订单延时,还原库存!

一、业务场景:当客户下单在指定的时间内如果没有付款,那我们需要将这笔订单取消掉,比如好的处理方法是运用延时取消,很多人首先想到的当然是crontab,这个也行,不过这里我们运用swoole的异步毫秒定时器来实现,同样也不会影响到当前程序的运行。

二、说明,order_status为1时代表客户下单确定,为2时代表客户已付款,为0时代表订单已取消(正是swoole来做的)

三、举例说明,库存表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),客户又可以继续下单了

这次我用swoole实现订单延时,还原库存!

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

下面贴出来纯手工PHP,很多同学用了原生PHP,就不会运用到框架里去,其实都一样的,不要想得那么复杂就是了。只要一点就是你用多了,你就会这样觉得咯。

配置文件config.php  ,这个在框架的话,基本上都是配置好了。

<?php
$dbHost = "192.168.23.110";
$dbUser = "root";
$dbPassword = "123456";
$dbName = "test";
?>

swoole都是用在linux系统里的,这里的host你可以自己搭建虚拟主机,也可以网上购买属于自己的服务器

订单提交的文件order_submit.php,这里对订单生成,同时扣除库存的一系列操作

<?php
require("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(
        &#39;order_amount&#39; => 10.92,
        &#39;user_name&#39; => &#39;yusan&#39;,
        &#39;order_status&#39; => 1,
        &#39;date_created&#39; => &#39;now()&#39;,
        &#39;product_lit&#39; => array(
            0 => array(
                &#39;product_id&#39; => 1,
                &#39;product_price&#39; => 5.00,
                &#39;product_number&#39; => 10,
                &#39;date_created&#39; => &#39;now()&#39;
            ),
            1 => array(
                &#39;product_id&#39; => 2,
                &#39;product_price&#39; => 5.92,
                &#39;product_number&#39; => 20,
                &#39;date_created&#39; => &#39;now()&#39;
            )
        )
    );
    try{
        $pdo->beginTransaction();//开启事务处理
        $sql = &#39;insert into csdn_order (order_amount, user_name, order_status, date_created) values (:orderAmount, :userName, :orderStatus, now())&#39;;
        $stmt = $pdo->prepare($sql);  
        $affectedRows = $stmt->execute(array(&#39;:orderAmount&#39; => $orderInfo[&#39;order_amount&#39;], &#39;:userName&#39; => $orderInfo[&#39;user_name&#39;], &#39;:orderStatus&#39; => $orderInfo[&#39;order_status&#39;]));
        $orderId = $pdo->lastInsertId();
        if(!$affectedRows) {
            throw new PDOException("Failure to submit order!");
        }
        foreach($orderInfo[&#39;product_lit&#39;] as $productInfo) {
            $sqlProductDetail = &#39;insert into csdn_order_detail (order_id, product_id, product_price, product_number, date_created) values (:orderId, :productId, :productPrice, :productNumber, now())&#39;;
            $stmtProductDetail = $pdo->prepare($sqlProductDetail);  
            $stmtProductDetail->execute(array(&#39;:orderId&#39; => $orderId, &#39;:productId&#39; =>  $productInfo[&#39;product_id&#39;], &#39;:productPrice&#39; => $productInfo[&#39;product_price&#39;], &#39;:productNumber&#39; => $productInfo[&#39;product_number&#39;]));
            $sqlCheck = "select product_stock_number from csdn_product_stock where product_id=:productId";  
            $stmtCheck = $pdo->prepare($sqlCheck);  
            $stmtCheck->execute(array(&#39;:productId&#39; => $productInfo[&#39;product_id&#39;]));  
            $rowCheck = $stmtCheck->fetch(PDO::FETCH_ASSOC);
            if($rowCheck[&#39;product_stock_number&#39;] < $productInfo[&#39;product_number&#39;]) {
                throw new PDOException("Out of stock, Failure to submit order!");
            }
            $sqlProductStock = &#39;update csdn_product_stock set product_stock_number=product_stock_number-:productNumber, date_modified=now() where product_id=:productId&#39;;
            $stmtProductStock = $pdo->prepare($sqlProductStock);  
            $stmtProductStock->execute(array(&#39;:productNumber&#39; => $productInfo[&#39;product_number&#39;], &#39;:productId&#39; => $productInfo[&#39;product_id&#39;]));
            $affectedRowsProductStock = $stmtProductStock->rowCount();
            //库存没有正常扣除,失败,库存表里的product_stock_number设置了为非负数
            //如果库存不足时,sql异常:SQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in &#39;(`test`.`csdn_product_stock`.`product_stock_number` - 20)&#39;
            if($affectedRowsProductStock <= 0) {
                throw new PDOException("Out of stock, Failure to submit order!");
            }
        }
        echo "Successful, Order Id is:" . $orderId .",Order Amount is:" . $orderInfo[&#39;order_amount&#39;] . "。";
        $pdo->commit();//提交事务
        //exec("php order_cancel.php -a" . $orderId . " &");
        pclose(popen(&#39;php order_cancel.php -a &#39; . $orderId . &#39; &&#39;, &#39;w&#39;));
        //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();
}
?>

订单的延时处理order_cancel.php

<?php
require("config.php");
$queryString = getopt(&#39;a:&#39;);
$userParams = array($queryString);
appendLog(date("Y-m-d H:i:s") . "\t" . $queryString[&#39;a&#39;] . "\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[&#39;a&#39;];  
            $sql = "select order_status from csdn_order where order_id=:orderId";  
            $stmt = $pdo->prepare($sql);  
            $stmt->execute(array(&#39;:orderId&#39; => $orderId));  
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            //$row[&#39;order_status&#39;] === "1"代表已下单,但未付款,我们还原库存只针对未付款的订单
            if(isset($row[&#39;order_status&#39;]) && $row[&#39;order_status&#39;] === "1") {
                $sqlOrderDetail = "select product_id, product_number from csdn_order_detail where order_id=:orderId";  
                $stmtOrderDetail = $pdo->prepare($sqlOrderDetail);  
                $stmtOrderDetail->execute(array(&#39;:orderId&#39; => $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(&#39;:productNumber&#39; => $rowOrderDetail[&#39;product_number&#39;], &#39;:productId&#39; => $rowOrderDetail[&#39;product_id&#39;]));
                }
                $sqlRestoreOrder = "update csdn_order set order_status=:orderStatus where order_id=:orderId";  
                $stmtRestoreOrder = $pdo->prepare($sqlRestoreOrder);
                $stmtRestoreOrder->execute(array(&#39;:orderStatus&#39; => 0, &#39;:orderId&#39; => $orderId));
            }
            $pdo->commit();//提交事务
        }catch(PDOException $e){
            echo $e->getMessage();
            $pdo->rollback();
        }
        $pdo = null;
        appendLog(date("Y-m-d H:i:s") . "\t" . $queryString[&#39;a&#39;] . "\t" . "end\t" . json_encode($queryString));
    }, $pdo);
} catch (PDOException $e) {
    echo $e->getMessage();
}
function appendLog($str) {
    $dir = &#39;log.txt&#39;;
    $fh = fopen($dir, "a");
    fwrite($fh, $str . "\n");
    fclose($fh);
}
?>

更多swoole技术文章,请访问swoole教程栏目!

以上是这次我用swoole实现订单延时,还原库存!的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:磊丰。如有侵权,请联系admin@php.cn删除

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),