Существует два наиболее популярных способа, позволяющих узнать о наличии в заданном массиве заданного ключа:
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.