我有以下似乎永远运行的功能。它创建一个随机字符串,然后检查它是否在数据库中。如果它是它应该一次又一次地运行,直到它有一个是新的。然后它应该将值返回给我
public function checkPromo(){
$continue = true;
while ($continue){
$promo = $this->getRandString(6);
$query = sprintf("SELECT * FROM table WHERE field=%s",
$this->db->cleanCode($promo, "text"));
$result = $this->db->query($query);
if($this->db->num_rows($result) >= 1){
$continue = false;
}
}
return $promo;
}
答案 0 :(得分:2)
请注意,您也很容易使用race conditions代码(从这个角度考虑)。
有两种方法可以生成唯一ID:
你结合了两个世界中最糟糕的东西:你正在使用一个中央系统来跟踪你的id,但你正在使用随机id生成它。使用其中一个,而不是两个。
如果您打算使用数据库,只需使用标准的auto_increment id即可。如果您希望它看起来有点随机,请使用MD5等进行哈希处理。
或者,简单的预生成所有可能的代码(只有6个字符不是很多),并使用不易受竞争条件影响的方法随机选择一个。有点像这样:
UPDATE codes
SET claimed_user_id = %d
WHERE claimed_user_id IS NULL
ORDER BY RAND()
LIMIT 1
否则,如果您想要分散的随机ID,请使用适当的算法,这几乎是UUID。
答案 1 :(得分:0)
while (true)
是一件危险的事情。正如您所指出的,它默认为一次又一次地运行创建infinite loop。
使用auto-incremented value(链接假定为MySQL)或使用PHP生成伪唯一ID(例如uniqid()
),你会更好。
您可以通过为常用单词添加前缀或后缀,例如促销,填充或散列它们来创建标准长度,从而进一步扩展这些值。
答案 2 :(得分:-2)
假设您只是想生成一个未记录在数据库中并考虑到上下文的promocode,我建议您稍微改变一下态度:
public function generatePromo(){
$promo = $this->getRandString(6);
$query = sprintf("SELECT * FROM table WHERE field=%s", $this->db->cleanCode($promo, "text"));
$result = $this->db->query($query);
if($this->db->num_rows($result) > 0){ # in case a record with this "text" already exists, run this method again
$this->generatePromo();
} else {
return $this->promo = $promo; # otherwise return the value/store it in the object
}}
如果您希望您的表格仅包含唯一值,那么我建议您将其设为UNIQUE
。这将大大缩短查询时间。