2015-04-17 64 views
0

我有以下函数似乎永远运行。它创建一个随机字符串,然后检查它是否在数据库中。如果是的话,它应该一次又一次运行,直到它有一个新的。它应该然后返回给我的价值检查随机字符串不在数据库中

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; 
     } 

回答

-2

假设你只是想生成没有记录在数据库中的促销码,并考虑到环境中,我劝你改变态度一点点:

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。这将显着减少查询时间。

+1

这段代码很容易出现竞争状况,甚至可能导致堆栈溢出。它还包含一个bug,它不会从递归调用中返回任何东西。 – deceze

+1

添加一条评论以使其更清晰:此代码采用与问题中相同的不可取的方法。如果没有找到合适的随机字符串,它也会使它变成递归函数而变得更糟,易受堆栈溢出的影响。随着更多的随机字符串被添加,代码仍然会呈指数级慢。 – Grampa

0

while (true)是一件危险的事情。如您所述,其默认为反复运行创建infinite loop

你会利用auto-incremented value更好的报价(链接假定MySQL的),或者用PHP生成一个唯一的ID(如uniqid())。

您可以通过前缀或后缀普通单词,例如promo或padding或散列它们以创建标准长度来进一步扩展这些值。

+0

请注意,您链接的'uniqid'功能对于生成唯一标识非常不利。 – deceze

2
  1. 您的具体问题是您的支票倒退。您正在循环播放,直到您找到重复的内容,这可能需要一段时间或永​​久。
  2. 即使您修复了它,这也是一个糟糕的算法。由于重复数据的机会增加,因此数据库中的代码越多,生成新的唯一代码的时间就会越长。特别是如果你的代码长度只有6个字符,重复的机会就会增加很多。

请注意,您也倾向于使用代码race conditions(从这个角度思考)。

有两种方法来生成唯一ID:

  1. 使用递增计数器,这意味着你使用的是中央发生器,它保持现有的IDS的轨道
  2. 用分散的方式,你是跟踪你的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

+0

我会尝试抢先评论关于MD5的任何评论:这里几乎没有安全问题,因为这里没有什么可以攻击的。 MD5对此很好,它的哈希值很短(ish)。 – deceze