2013-06-28 15 views
0

我有一個數組,其中包含IP地址及其各自的子網信息。在第一時間,我一定要子網信息添加到我的數據庫,但我想沒有任何重複這樣做,與此代碼多個foreach中的PHP未設置數組

#Note that this is pseudo-code 
foreach ($subnets as $subnet) 
{ 
    $query = 'INSERT INTO subnets (field1, field2) 
       VALUES ($subnet['subnet'], $subnet['netmask']);' 

    $database->executeQuery($query); 

    $query = 'SELECT id FROM subnets 
       WHERE subnet = $subnet['subnet'] 
       AND mask = $subnet['netmask'];' 
    $subnet_id = $database->getRow($query); 

    foreach ($subnets as $key => $subnet_check) 
    { 
     if (($subnet['subnet'] == $subnet_check['subnet']) AND ($subnet['netmask'] == $subnet_check['netmask'])) 
     { 
      $ip_to_add = array_merge($ip_to_add,array(array("subnet_id" => $subnet_id[0], "ip" => $subnet['ip'], "name" => $subnet['name']))); 
      unset($subnets[$key]); 
     } 
    } 
} 

第一的foreach將增加每個子網和檢索他們的每一個ID的。 第二個foreach將掃描每個子網並嘗試查找重複(包括其本身)。如果是這樣,它應該將ip地址信息添加到數組中,然後取消設置此元素,因爲我們不想在另一個循環中重新插入子網。

然而,這似乎並沒有正確解決它,因爲最後,每個子網和IP地址都被插入(插入所有的子網會帶來很多重複)。

任何人都可以向我解釋爲什麼unset工作不正常?是因爲我進入了2級的foreach嗎?

謝謝。

+5

你有沒有考慮扭轉這個順序?首先檢查數據庫,並且只在沒有找到匹配的情況下添加新記錄?而不是添加,然後檢查,然後刪除 – Dave

回答

1

PHP中的foreach()語句祕密地複製數組並迭代該副本。這沒有任何性能影響,因爲它使用了寫時複製語義,因此只有在您寫入到foreach循環中時才真正將數組複製到內存中。你在這裏做什麼。所以你的兩個循環實際上迭代了$ subnets數組的兩個不同副本。當你從一個數組中取消設置時,這不會對另一個產生任何影響。

解決這個問題的最簡單方法是指示PHP不要複製。請在這兩個循環的這種變化:

foreach(array() as &$row) {} 

foreach(array() as $key => &$row) {} 

這就是說,我認爲在這裏你的算法還有待改進。 那麼什麼好像你正在做的是:

  1. 迭代每個子網
  2. 插入
  3. 查詢插入的行的ID
  4. 再次重申數組和添加項目到$包含該ID的ip_to_add。

我的問題是,你想$ ip_to_add看起來像到底什麼?現在看來,如果有重複項,只有一個插入到表中,但$ ip_to_add將有重複的行?它看起來像$ ip_to_add將具有相同數量的項目作爲您的原始$子網陣列?那是你需要的嗎?

如果沒有,我會做的是:

  1. 重複數據刪除陣列
  2. 迭代它,將它插入,使用mysql_insert_id()來獲取ID,並添加到陣列中。