热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

64图裁剪php_swoole+PHP实现自动取消订单,还原库存等操作

一、业务场景:当客户下单在指定的时间内如果没有付款,那我们需要将这笔订单取消掉,比如好的处理方法是运用延时取消,这里我们用到

一、业务场景:当客户下单在指定的时间内如果没有付款,那我们需要将这笔订单取消掉,比如好的处理方法是运用延时取消,这里我们用到了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),客户又可以继续下单了

f9a83579e34f7a73663a513031b6dfd0.gif

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

$dbHost = "192.168.0.110";
$dbUser = "root";
$dbPassword = "123456";
$dbName = "test123";
?>

3、order_submit.php,生成订单

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

4、order_cancel.php&#xff0c;这个方法主要就是做订单自动取消&#xff0c;并还原库存的业务处理

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

以上内容希望帮助到大家&#xff0c;很多PHPer在进阶的时候总会遇到一些问题和瓶颈&#xff0c;业务代码写多了没有方向感&#xff0c;不知道该从那里入手去提升&#xff0c;对此我整理了一些资料&#xff0c;包括但不限于&#xff1a;分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6&#xff0c;laravel&#xff0c;YII2&#xff0c;Redis&#xff0c;Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家&#xff0c;需要请戳这里链接 或 者关注咱们下面的知乎专栏
PHP架构师圈子​zhuanlan.zhihu.com
6a3397ad15505668b4adb00ed17972fb.png

来源链接&#xff1a;https://blog.csdn.net/WanTianwen/article/details/82693677




推荐阅读
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文主要复习了数据库的一些知识点,包括环境变量设置、表之间的引用关系等。同时介绍了一些常用的数据库命令及其使用方法,如创建数据库、查看已存在的数据库、切换数据库、创建表等操作。通过本文的学习,可以加深对数据库的理解和应用能力。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • centos 编译安装 php 5.5,CentOS 5.5上编译安装 PHP 5.3.6
    编译并安装#make&&makeinstall安装结果摘要,里面有几个主要的安装路径变量libtool:install:warning:remembertorunli ... [详细]
  • sql注入学习笔记,什么是sql注入,如何预防sql注入,如何寻找sql注入漏洞,如何注入sql攻击 (原)...
    (整篇文章废话很多,但其实是为了新手能更好的了解这个sql注入是什么,需要学习的是文章最后关于如何预防sql注入)ÿ ... [详细]
  • phpgettext.dll的简单介绍
    本文目录一览:1、在php.ini中设置了extension=php_gettext.dl ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
author-avatar
斿荡
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有