читатель,
Недавно я потерял 40 минут на отладку, потому что коллега допустил небольшую ошибку, дублируя строки, а PHP не вызвал никакой ошибки.
Оригинальные линии были похожи на
$files = [
'identifier1' => '/path/to/file1'
];
Намеченные строки после дублирования
$files = [
'identifier1' => '/path/to/file1',
'identifier2' => '/path/to/file2',
'identifier3' => '/path/to/file3'
];
Как на самом деле были линии
$files = [
'identifier1' => '/path/to/file1',
'identifier1' => '/path/to/file2',
'identifier1' => '/path/to/file3'
];
Который так же, как
$files = [
'identifier1' => '/path/to/file3'
];
Есть ли способ заставить php вызвать ошибку (даже если это всего лишь предупреждение), когда вы по ошибке пытаетесь определить массив с дублирующимися ключами?
Мы хотели бы включить эту опцию глобально, и error_reporting (E_ALL) не работает, к сожалению.
Это не считается ошибкой в PHP. Это просто перезапись пары ключ / значение.
Единственный способ проверить это — проверить count()
из $files
после того, как вы определите его, чтобы проверить, есть ли у него столько пунктов, сколько вы считаете нужным. Затем вы можете бросить Exception
или зарегистрируйте ошибку, если число слишком мало.
Если вы предоставляете свой источник в виде предварительно созданного массива:
$list = [
'one' => 1,
'two' => 2,
'one' => 3,
];
Тогда просто невозможно обнаружить дубликаты ключей с проверкой во время выполнения, так как этот код скомпилирован, как если бы это было:
$list = [
'two' => 2,
'one' => 3,
];
Т.е. дублированный ключ по существу исчезает до запуска вашего кода, и любой код, который вы пишете, просто никогда не увидит первую запись. Если вы пишете свой код в виде отдельных строк:
$list['one'] = 1;
$list['two'] = 2;
$list['one'] = 3;
Тогда у вас есть несколько вариантов. Вы можете создать класс, который реализует ArrayAccess
затем напишите offsetSet()
метод, чтобы проверить, существует ли данное смещение, когда записывается новое смещение. Класс, по сути, будет использоваться везде, где есть массив.
class UniqueArray implements ArrayAccess
{
protected $data = [];
public function offsetExists($key)
{
return array_key_exists($key, $this->data);
}
public function offsetGet($key)
{
return $this->data[$key];
}
public function offsetSet($key, $value)
{
if ($this->offsetExists($key)) {
throw new Exception("key '$key' already exists");
}
$this->data[$key] = $value;
}
public function offsetUnset($key)
{
unset($this->data[$key]);
}
}
$list = new UniqueArray();
$list['one'] = 1;
$list['one'] = 2; // throws an exception
Я думаю, что это, вероятно, больше проблем, чем оно того стоит.
Ваш единственный реальный вариант — статический анализ кода. Вы могли бы написать свой собственный анализ для PHPCS который пытается найти эти дубликаты ключей в фактическом исходном коде. Обратите внимание, что для обнаружения проблем потребуется запустить инструмент анализа исходного кода.