БлогNot. PHP: разница между массивами и "дырки" в порядке заполнения id

PHP: разница между массивами и "дырки" в порядке заполнения id

Представим себе типичную таблицу БД, в которой записи идентифицируются по полю-счётчику id, автоматически "нумерующему" записи.

Лучший вариант обращения с такими таблицами - вообще ничего не удалять из базы, чтобы id гарантированно имели значения 1, 2, 3 и т.д. Это позволит, например, без проблем извлекать случайную запись из базы и всегда быть уверенным, что идентификатор последней записи соответствует количеству записей в таблице. Задачи администрирования (удаления) некоторых записей при этом можно решать так, как делается на многих форумах сети - контент заменяется строкой "Эта запись удалена администратором" или чем-то подобным.

К сожалению, в жизни таких идеальных ситуаций практически не бывает и в таблице обязательно оказываются "дырки", то есть, "пропущенные" из-за удалённых записей или по ещё каким-то причинам id. Также по разным причинам администратор иногда хочет получить список таких идентификаторов :) Показанный ниже код - пример несложного скрипта PHP, который для этой цели можно выполнить на сервере.

Предполагается, что нужные данные содержатся в поле id таблицы messages базы данных test, конечно, всё это легко поменять в коде. Для доступа к базе используется современный интерфейс mysqli вместо устаревающего mysql.

Также код иллюстрирует подход к задаче поиска "дырок" в подряд идущих значениях 1,2,3,...,$max. Сначала результаты запроса преобразуются в массив $arr1, состоящий только из упорядоченного по возрастанию списка существующих в таблице id, затем формируется массив $arr2, содержащий числа 1,2,3,...,$max без пропусков, где $max - максимальный (последний) из полученных id. После этого нам остаётся только сравнить массивы стандартной функцией array_diff и вывести информацию об отличиях.

Скрипт проверен на локальном хосте Denwer с PHP 5.5.

<?php
 error_reporting (E_ALL);

 $mysqli = new mysqli("localhost", "root", "", "test"); //хост, логин, пароль, база
 if ($mysqli->connect_errno) {
  printf("Connect failed: %s\n", $mysqli->connect_error);
  exit ();
 }

 $query = "SELECT id FROM messages ORDER by id asc"; //поле id из таблицы messages
 $arr1 = array ();
 if ($result = $mysqli->query($query)) {
  while ($row = $result->fetch_row()) {
   $arr1[] = $row[0];
  }
  $result->close();
 }
 else {
  printf ("Ошибка выполнения запроса: $query, сообщение: %s<br>\n",$mysqli->error);  
  exit ();
 }
 $mysqli->close();

 $max = $arr1[count($arr1)-1];
 $arr2 = array ();
 for ($i=1; $i<=$max; $i++) $arr2[] = $i;
 $diff = array_diff ($arr2 , $arr1);

 echo '<p>Отсутствующие id: ';
 foreach ($diff as $item) echo $item.' ';
 echo '</p><p>Всего отсутствует: '.count ($diff).'</p>';
?>

26.12.2017, 22:06 [2168 просмотров]


теги: php mysql алгоритм

К этой статье пока нет комментариев, Ваш будет первым