2013-06-28 3 views
0

У меня есть массив, содержащий ip-адреса и их соответствующую информацию о подсети. В первый раз, я должен добавить информацию подсети в мою базу данных, но я пытаюсь сделать это без каких-либо двух экземпляров, с этим кодомPHP unset array в нескольких foreach

#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 сканирует каждую подсеть и попытается найти дубликат (включая его). Если это так, он должен добавить информацию об адресе ip-адреса в массив, а затем отключить этот элемент, поскольку мы не хотим повторно вставлять подсеть в другой цикл.

Однако, похоже, что это не похоже на правильное удаление, так как в конце вставляются все подсетей и IP-адреса (вставка всей подсети приносит много дубликатов).

Может ли кто-нибудь объяснить мне, почему unset не работает правильно? Это потому, что я нахожусь на уровне 2-го уровня?

спасибо.

+5

Вы считаете отмену этого заказа? сначала проверьте базу данных и добавьте новые записи, если совпадений не найдено? вместо добавления, затем проверки, затем удаления – Dave

ответ

1

Оператор foreach() в PHP тайно делает копию массива и выполняет итерацию, которая копирует. Это не влияет на производительность, поскольку использует семантику Copy-on-Write, поэтому массив копируется только в память, если вы пишете ее внутри цикла foreach. Что вы здесь делаете. Таким образом, ваши две петли фактически перебирают более двух разных копий массива $ subsnets. Когда вы отключаетесь от одного массива, это не повлияет на другой.

Самый простой способ исправить это будет инструктировать PHP, чтобы НЕ сделать копию. Сделать это изменение в обеих ваших петлях:

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

или

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

То есть, я думаю, ваш алгоритм здесь может быть улучшен. Так что, похоже, что вы делаете это:

  1. Iterate каждая подсеть
  2. Вставка
  3. Запрос на идентификатор вставленной строки
  4. Re-перебирать массив и добавить элемент в $ ip_to_add, который включает идентификатор.

Мой вопрос: что вы хотите, чтобы $ ip_to_add выглядел в конце? Похоже, прямо сейчас, если есть дубликаты, у вас будет только одна вставка в таблицу, но $ ip_to_add будет иметь повторяющиеся строки? Кажется, что $ ip_to_add будет иметь такое же количество элементов, как ваш исходный массив $ subnets? Это то, что вам нужно?

Если нет, то я хотел бы сделать это:

  1. De-надуть массив со
  2. итерацию его, вставить его, используйте mysql_insert_id(), чтобы получить идентификатор и добавить, что в массив.