我使用的是PHP laravel 7,我有一个优惠券表,其中有一个字段叫代码,这个代码是8个字符(数字和字符)这个代码应该是唯一的优惠券记录,在管理面板上,我有一个按钮的管理用户,他可以点击并生成尽可能多的优惠券,他想。
我将在我的php代码中使用以下函数生成唯一的字符串。
substr(uniqid(), 0, 8)
然后我会执行一个查询,检查是否有任何优惠券在我的表中,它的代码等于我新生成的代码之一。
$model->newQuery()->whereIn('code', $generated_codes)->get();
如果结果列表是空的,那很好,我要把我所有的代码都插入到数据库中。如果列表不是空的,我要从我生成的代码中删除重复的代码,同时根据重复代码的数量再次生成新的代码,并再次重复这个过程,我要重复这个过程,只要没有生成的代码存在于数据库中,然后我就把它们插入数据库。
我的问题和这个问题不同。我的问题和这个问题不同: 如何生成一个随机的、唯一的、字母数字的字符串?
因为我正在生成很多独特的代码,而不仅仅是代码,然后我要把这些代码插入数据库,我需要有最少的查询次数。
这里的东西东西,可能会工作。
function generateRandomCodes($number) {
$codes = Collection::times($number, function () { Str::random(8); });
$affected = DB::table('your_table')
->insertOrIgnore($codes->map(function ($code) {
return [ 'code' => $code, /* more fields? */ ];
});
if ($affected < $number) {
generateRandomCodes($number-$affected);
}
}
insertOrIgnore
插入和覆盖数据时,将忽略重复的键。这是非常有用的,因为它避免了插入之前的查找,这可能是昂贵的,这个 应 回数 受影响 行,即创建新行。如果它无法插入所有需要的代码,那么它就会 应 再次运行它来处理剩余的代码。这一切的前提是 code
是主键。
我没有亲自测试过,所以我建议你在任何生产代码中使用它之前先测试一下。
一些额外的说明。
Str::random
内部使用一个base64编码的字符串 random_bytes
这是加密安全的(虽然不知道base64版本在技术上是否算作安全,也不知道最终结果是否真的安全)。这意味着有62^8=2*10^14种组合,你可以得到字符(+,=和被删除)。这是一个高得离谱的数字,你不应该真正期待碰撞的发生,直到你产生了这些数字中的大约10%(大约2*10^13)。不过 假设您将这些内容存储在 区分大小写 列,默认情况下,数据库中的字符串列为 不 区分大小写,这将你的唯一组合减少了三分之二(这仍然是一个相当大的数字),这意味着你不会真的需要调用这个函数一次以上,除非你真的那么 "幸运"
你可以使用这种类型的函数来获取唯一的优惠券代码。
function generateCode(){
$code = substr(uniqid(), 0, 8);
$exists = YourModel::where('code', $code)->count();
if($exists > 0){
$this->generateCode();
}
return $code;
}
你可以使用firstOrCreate(),但事实上它可能会执行很多查询。希望能帮助U找到好的解决方案
public function initCoupon()
{
$code = substr(uniqid(), 0, 8);
$new = false;
do {
$coupon = CouponModel::firstOrCreate(compact('code'));
$new = $coupon->wasRecentlyCreated
} while(!$new);
return $coupon;
}
比U可以设置额外的优惠券数据