生成唯一订单号
最后更新于:2022-04-02 04:33:46
## 生成唯一订单号
确保生产唯一的订单号,字段建立唯一索引。
* * * * *
### 一般方案
```php
for ($i = 0; $i < $data['createnum']; $i++) {
do {
// $code = strtolower(get_rand_str(8, 0, 1)); // 获取随机8位字符串
// 零填充导致Excel显示数字不正确
$code = zerofill(mt_rand(0, 99999999), 8, 9);
$password = mt_rand(1000, 9999); // 获取随机4位数字
$check_exist = M('exchange_list')->where(array('code' => $code))->find();
} while ($check_exist);
$add['code'] = $code;
$add['password'] = $password;
$newId = M('exchange_list')->add($add);
if (!$newId) {
exit('重复!');
} else {
}
}
```
https://coding.net/u/xiasf/p/gj-shop/git/blob/master/Application/Admin/Controller/ExchangeController.class.php
这里只知道插入失败就表示重复,其实这是不准确的,有可能是别的原因导致插入失败呢,不一定是重复原因,除非能得到sql失败的错误码,每种情况都有一个系统确定的错误码,比如重复有一个错误码。
重复不能失败,而是要重试。
* * * * *
### 终极方案
```php
/* 插入订单表 */
$error_no = 0;
do
{
$order['order_sn'] = get_order_sn(); //获取新订单号
$GLOBALS['db']->autoExecute($GLOBALS['ecs']->table('order_info'), $order, 'INSERT');
$error_no = $GLOBALS['db']->errno();
if ($error_no > 0 && $error_no != 1062)
{
die($GLOBALS['db']->errorMsg());
}
}
while ($error_no == 1062); //如果是订单号重复则重新提交数据
$new_order_id = $db->insert_id();
$order['order_id'] = $new_order_id;
```
这里更加完善就是能够识别到重复插入(唯一索引限制)报错的错误码:1062
不过这个错误码可能每个数据库系统都不一样。
这种方式应该是最完美安全的终极方案了。
[电商网站订单号怎么生成呢?我目前用订单ID来做感觉不行,从1开始这样太不好看了,像淘宝那样的订单ID怎么生成的呢? - apple的回答 - SegmentFault 思否](https://segmentfault.com/q/1010000004104517/a-1020000014209988)
* * * * *
```php
// tpDb操作出错要抛出异常,只能这么处理了。
// 如果这步骤出错,基本就是重复的问题,那么一直重试,再次生成邀请码更新进去,直至成功
do {
try {
// 生成唯一邀请码
Db::name('user')->where('id', $newId)->update([
'invitation_code' => createInvitationCode(),
]);
$upStatus = 1;
} catch (\Exception $e) {
trace('createInvitationCode: [' . $e->getCode() . '] ' . $e->getMessage(), 'error');
$upStatus = 0;
}
} while ($upStatus == 0);
```
* * * * *
### 扩展
[分布式ID生成器 | 架构师之路](http://mp.weixin.qq.com/s/AHRCYOjnXAgcy2j6vziukQ)
[如何做一个靠谱的发号器](https://tech.youzan.com/id_generator/)
* * * * *
last update:2018-4-10 04:45:12
';