array_diff() странное поведение
В моем коде есть подпрограмма, которая вычисляет различия между двумя массивами, чтобы создать оператор SQL UPDATE.
Как только процедура запускается, я создаю копию входного массива, чтобы манипулировать им, пока входной не трогается. Когда я готов создать оператор UPDATE, я вычисляю разницу между ними, используя модифицированный массив в качестве ведущего.
В каждом тесте, который я запускал, оба массива были заполнены парами ключ = значение, и все значения были строками, даже если они были целыми числами в базе данных (поведение PDO) и до сих пор все работало безупречно.
Но сейчас я нашел что-то странное. Два разных действия в двух разных контроллерах, но с одинаковой логикой приводят к разным различиям:
Этот работает как ожидалось:
$input = array(
'tid' => '3',
'enabled' => '1'
);
$modified = array(
'tid' => '3',
'enabled' => 0,
'modified' => '2014-11-26 15:17:55'
};
$diff = array(
'enabled' => 0,
'modified' => '2014-11-26 15:17:55'
);
$ input является результатом запроса. $ified - это копия первого массива, обработанного методами класса. Когда я готов создать оператор, $ diff вычисляется для того, чтобы отправить в PDO (или другой драйвер) правильный оператор.
Здесь работает array_diff(). индекс tid присутствует в обоих массивах и игнорируется. Включенный простой флаг включения / выключения отличается и он включен. Представление даты и времени тоже.
Но посмотрите переменные этого другого случая:
$input2 = array(
'sid' => '1',
'finished' => '0'
);
$modified2 = array(
'sid' => '1',
'finished' => 1,
'modified' => '2014-11-26 15:21:58'
);
$diff2 = array(
'modified' => '2014-11-26 15:21:58'
);
Так же, как и раньше, но с разными именами полей. Sid игнорируется, но готовый тоже игнорируется, хотя не должен, потому что его нет в $ input.
Заменив array_diff() на array_diff_assoc(), как и ожидалось, все работает, но почему?
1 ответ
Из документов:
массив array_diff (массив $array1, массив $array2 [, массив $... ])
Сравнивает массив1 с одним или несколькими другими массивами и возвращает значения в массиве1, которых нет ни в одном из других массивов.
В вашем примере $modified2
имеет запись "готово", которая имеет значение 1. Но $input2
также имеет значение 1 для ключа 'sid'. Таким образом, используя array_diff($modified2, $input2)
приведет к удалению каждой записи со значением 1, независимо от того, какой это ключ.
С помощью array_diff_assoc
, он будет только проверять, если $input2
имеет запись 'finish' => 1, чего нет, поэтому запись не будет удалена.