为什么创建订单这里循环 10 次?

public static function findAvailableNo()
    {
        // 订单流水号前缀
        $prefix = date('YmdHis');
        for ($i = 0; $i < 10; $i++) {
            // 随机生成 6 位的数字
            $no = $prefix.str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            // 判断是否已经存在
            if (!static::query()->where('no', $no)->exists()) {
                return $no;
            }
        }
        \Log::warning('find order no failed');

        return false;
    }
欲速则不达
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
leo
最佳答案

假如由于某种原因 static::query()->where('no', $no)->exists() 始终返回 true,那这里就会有陷入死循环的风险,因此我们限定只试 10 次。

5年前 评论
讨论数量: 8
leo

假如由于某种原因 static::query()->where('no', $no)->exists() 始终返回 true,那这里就会有陷入死循环的风险,因此我们限定只试 10 次。

5年前 评论

你明白leo 的回答了? 你不是问为什么要循环10次嘛? 不循环就不会陷入死循环啊。。。难道是我智商捉急了没有理解上去嘛? 哈哈

5年前 评论

@AmberLavigne 有时候生成的订单号在数据库中已经存在,需要再次获取,所以需要在一定次数内循环获取,不然就会订单失败。

5年前 评论

@JaydenHong 道理我懂,但是这里不需要这么写,作者说的某种情况是什么情况?
应该和生成优惠卷逻辑相似才是最优解。

/**

生成优惠卷编号
@param int $length
@return string
*/
public static function findAvailableCode($length = 16)
{
do {
$code = strtoupper(Str::random($length));

} while (
    self::query()->where('code',$code)->first()
);

return $code;
}
5年前 评论

@leo 大佬 能举例子吗 还是没懂 想了好久了

5年前 评论

@等车的猪 我来大概说说我的看法吧:

//这里查数据库  有可能数据库 有相同的 订单号存在  那么这里就返回true
// 那么findAvailableNo() 方法  返回false
static::query()->where('no', $no)->exists()
//模型的这个方法 是在订单记录生成之前 自动生成订单号的 那么因为数据库中有重复的订单 所以 这个方法 返回false
//订单生成 失败   如果加了那个十次的 for  循环的话  当 有重复订单号的时候 
//再次 生成新的订单号 这样 出现重复订单号的几率减小  创建订单记录的几率增大  
//其实就是为了最大程度排除生成重复订单号的可能
    protected static function boot()
    {
        parent::boot();
        // 监听模型创建事件,在写入数据库之前触发
        static::creating(function ($model) {
            // 如果模型的 no 字段为空
            if (!$model->no) {
                // 调用 findAvailableNo 生成订单流水号
                $model->no = static::findAvailableNo();
                // 如果生成失败,则终止创建订单
                if (!$model->no) {
                    return false;
                }
            }
        });
    }
5年前 评论

这个订单号的生成方法非常好!
正常情况下,循环第一次就可以得到唯一的订单号,此时return语句立即跳出循环并返回订单号。即便有百万分之一的概率,创建了一个已经存在的订单号,也不必担心!由于循环体的存在,程序会再次尝试第二次创建唯一订单号。正常情况下,这个循环体只会执行一次就结束。

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!