Существует два наиболее популярных способа, позволяющих узнать о наличии в заданном массиве заданного ключа:
1. isset — Определяет, была ли установлена переменная значением отличным от NULL
2. array_key_exists — Проверяет, присутствует ли в массиве указанный ключ или индекс
Пример:
$array = [
'first' => 1,
2 => 'second',
'third' => null
];
$isset_result = isset($array['first']);
$ake_result = array_key_exists('first', $array);
Какая же из них наиболее оптимальна?
Первое отличие двух этих способов в том, что isset — это языковая конструкция, а не функция, как array_key_exists.
Второе отличие в том, что isset проверяет не только лишь наличие заданного ключа в заданном массиве, а, так же, в случае нахождения значения по заданному ключу, ещё и соответствие этого значения NULL.
То есть, в следующем случае:
echo isset($array['third']) === array_key_exists('third', $array);
Результаты отработки isset и array_key_exists не будут равны и мы увидим false, т.к. в случае с isset заданный ключ найден, но значение для заданного ключа равно NULL. Следовательно, эта функция «посчитает», что заданного ключа и вовсе нет.
То есть, если вам необходимо проверить исключительно наличие ключа в заданном массиве и вас интересует исключительно его наличие (не важно, что значение под данным ключом может быть не задано или соответствовать NULL) то следует использовать array_key_exists.
Третье отличие в скорости работы.
Для тестирования скорости работы я создал достаточно большой массив (в тестах вариьровалось от 10 тысяч элементов до 10 миллионов элементов) «случайных» значений и, затем, в цикле (от 10к до 10кк итераций) я вызывал isset и array_key_exists.
Код примера:
$result = [];
// 1. Заполняем массив, в котором будем осуществлять поиск
$data = [];
$elementNames = ['perl', 'php', 'csharp', 'cpp', 'c', 'javascript', 'java'];
$elementNames_length = count($elementNames) - 1;
$numberOfElements = 10000;
for($i = 0; $i < $numberOfElements; $i++)
{
$randomKey = mt_rand(0, $elementNames_length);
$data['da'.mt_rand(mt_rand(100, ceil($numberOfElements/2)), $numberOfElements).'net'] = $i . $elementNames[$randomKey] . mt_rand(mt_rand(100, ceil($numberOfElements/2)), $numberOfElements);
}
// 2.1 Тестируем isset
$isset_start_time = microtime(true);
$isset_time = 0.00;
for($i = 0; $i < $numberOfElements; $i++)
{
$flush = isset($data['da'.$numberOfElements.'net']);
}
$isset_end_time = microtime(true);
$isset_time = $isset_end_time - $isset_start_time;
// 2.2 Тестируем array_key_exists
$ake_start_time = microtime(true);
$ake_time = 0.00;
for($i = 0; $i < $numberOfElements; $i++)
{
$flush = array_key_exists('da'.$numberOfElements.'net', $data);
}
$ake_end_time = microtime(true);
$ake_time = $ake_end_time - $ake_start_time;
// 3. Выводим результаты
$result[] = [
'isset' => $isset_time,
'ake' => $ake_time
];
echo '<pre>' . print_r($result, true) . '</pre>';
Далее, тесты на массиве разных размеров (от 10к до 10млн):
1. Результат (10000 элементов):
1. isset => 0.00714898109436
2. array_key_exists => 0.0171840190887
2. Результат для 100 тыс. элементов (100000 элементов):
1. isset => 0.0732381343842
2. array_key_exists => 0.175088882446
3. Результат для 1 млн. элементов (1000000 элементов):
1. isset => 0.757771015167
2. array_key_exists => 1.79065108299
4. Результат для 10 млн. элементов (10000000 элементов):
1. isset => 7.62896299362
2. array_key_exists => 17.4600510597
Из результата очевидно, что isset быстре. На «больших» же массивах это уже становится достаточно ощутимо.
В общем, можно сделать вывод, что isset — это более оптимальный способ проверить наличие заданного ключа в заданном массиве, но следует это делать не без осторожности, т.к. если заданный ключ в заданном массиве будет найден, то isset ещё и проверит найденное значение на NULL и в случае соотвествия вернёт false.