生成规则设计 http://hudeyong926.iteye.com/blog/1860360
订单号生成规则 系统时间随即号|系统时间数据库自增号
前阵子,公司有个电子商务项目,需要生成订单号。当时的考虑很简单,取系统时间加上随机数,或者使用 uniqid() 方法。我们都知道,订单号最基本的要求就是唯一,这个条件必须满足。仔细考虑下上述方法,在顾客购买量少的情况下,订单重复的可能性为零,但是在购买高蜂期生成的订单号重复是很有可能发生的 。所以上述方法不可靠,有待强化。
public function get_order_sn(){ //原来的订单号形式为:年月日 + 5位随机数字,例如:2012042096200 return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); return substr(md5(crypt(time()).rand(1, 10000)), 0, 6); }
用上了英文字母、年月日、Unix 时间戳和微秒数、随机数,重复的可能性大大降低,还是很不错的。使用字母很有代表性,一个字母对应一个年份,总共16位,不多也不少,呵呵。substr(time(), -3)
function get_order_sn($year='2011'){ $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'); $index = intval(date('Y')) - $year; if($index<0){ $index =0; } if($index>count($yCode)-1){ $index =count($yCode)-1; } $perfix = $yCode[$index] . strtoupper(dechex(date('m'))) . date('d'); $rand_num = substr(uniqid(),-6).substr(time(), -5) . substr(microtime(), 2, 5).sprintf('%03d', rand(0, 99)); $orderSn = $perfix . $rand_num; return $orderSn; }
1.如果生成订单不要求订单号连续,订单号CHAR(6)NOT NULL DEFAULT '',先保存订单后得到自增的主键,再根据主键更新订单号,高并发也不存在问题,推荐此方法 。
$id = last_insert_id(); 'M'. str_pad($id, 5, '0', STR_PAD_LEFT);
2.如果生成的订单要求订单号必须是连续的,并发加锁 ,要保证订单连续订单号必须在订单生成的同时++,但是多人同时操作时会出现订单号相同的冲突。解决方法:http://hudeyong926.iteye.com/blog/894823
$sql="SELECT `next_seq` FROM `create_seq_num` LIMIT 1;UPDATE `create_seq_num` SET `next_num`=`next_num` + 1";
建立一张订单号预约表,表中的订单号有效期1个小时,在有效期内被预约的号码会被用户占用,和优先使用,其他人不能使用,超过1小时就表示放弃了预约,如果用户还是用的是这个号码,就提示订单号失效了,用户必须重新获取订单号在继续操作。其他用户可以使用该号码。
当用户1在订单作业时,在使用订单号200910G0016时,这个订单号就被预约了,其他人就不能使用它了,其他人就只能用下一个订单号。在一个小时内,用户1没有完成一单,不管怎样重新下单他就只能使用订单号200910G0016,超过1小时候就不能使用了。如果完成了预约(将订单号200910G0016生成了一张订单,就要删除这个号)。
<?php $list = $this->getRegReserv(null, 2); //首先看预约表是否有该用户的预约订单号 if(empty($list)){ //没有预约去订单号表获取新订单号并预约 $no =$this->getSettingNo($field, $systemid); $sql="UPDATE settings SET ".$field."='".sprintf("%04d",($no+1))."' WHERE systemid='".$systemid."'"; $this->executeSQL($sql); $this->insertRegReserv($date.$no, 2); //将号码加到预约表中 return $date.$no; } //得到一个小时内用户1预约的订单号 function getRegReserv($selected_regs, $class){ $sql ="SELECT reg_no FROM reserv_num WHERE user_id ="$_SESSION['user']" and class='".$class."' and reserv_date <=(SELECT DATE_SUB(now(), INTERVAL 1 HOUR))"; if($selected_regs){ $sql .=" AND reg_no NOT IN (".stripslashes($selected_regs).")"; } $sql.=" ORDER BY id ASC LIMIT 1"; $list = $this->querySQL($sql); return $list; } //生成订单操作