Шрифт
Использование функций isset() и array_key_exists()
Play

Использование функций isset() и array_key_exists()

Навеяно проблемой, с которой я столкнулся из-за неправильного использования функции isset() в одном китайском движке интернет магазина. Там isset() применялась для определения существования элемента массива с некоторым ключом. Самое неприятное в данной ситуации то, что такую ошибку допускают многие. Это не первый случай, когда isset() используется именно в таком контексте, хотя это в корне неверно. Но в этот раз неграмотность разработчиков стоила мне потерянного времени, что и сподвигло меня на эту заметку.

Еще больше меня «порадовали» комментарии одного «незнакомого» знакомого, который удивился моему негодованию. Как оказалось, о существовании функции array_key_exists() он что-то слышал, но сам никогда ею не пользовался. Более того, где-то читал, что ее лучше заменять на isset() , так как последняя работает быстрее.

Собственно, об уровне квалификации PHP программистов сказано немало и добавить к этому нечего.

Инициализация и удаление переменной в PHP

В PHP переменная инициализируется в момент присваивания ей значения. Неинициализированной переменная считается в двух случаях:

  • ей не присваивалось никакого значения;
  • ей было присвоено значение типа NULL или она была передана функции unset() .

Присваивание NULL значения удаляет переменную, аналогично функции unset() , то есть делает ее неинициализированной.

Если попытаться использовать переменную, которая была удалена с помощью unset() , будет сгенерирована ошибка уровня E_NOTICE. С переменной, приведенной к NULL, такого не произойдет.

Функция isset()

Функция проверяет факт инициализации переменной. isset() вернет false, если передать ей в качестве параметра неинициализированную переменную. Тоже самое произойдет и с ключом массива, который имеет NULL значение. Для ключей массива действуют такие же правила приведения к NULL, как и для переменных.

Результат:

Функция array_key_exists()

Работа функции array_key_exists() похожа на isset() , но с той лишь разницей, что даже для ключа с NULL значением будет возвращено TRUE.

Чтобы полностью удалить пару ключ-значение необходимо использовать unset() .

Для массива использование NULL значения ключа удобно, если наличие ключа требуется сохранить. Можно будет рассчитывать на контекст, в котором данный ключ будет использован. Например, это удобно при заполнении полей формы дефолтными значениями. Например, при использовании конструкции echo, NULL значение будет приведено к пустой строке.

То, к чему я клоню, мне кажется очевидным. Если вы работаете с ключами массива, то используйте именно ту функцию, которая для этого предназначена. Ко всему прочему, использование array_key_exists() позволяет точно понять логику приложения. Никакой двусмысленности не возникает.

Скорость работы isset() и array_key_exists()

О том, что array_key_exists() работает медленнее isset() пишут даже в комментариях к соответствующей странице PHP мануала. Жалуются на то, что более медленная работа array_key_exists() заметна на массивах с количеством пар ключ-значение, превышающих 200.

Ничего не остается, как прогнать банальный тест:

Ассоциативный массив $testArray содержит 10 000 элементов. Это несколько больше, чем упомянутые 200.

Далее прогоняем цикл с количеством итераций 100 000. В теле цикла, по очереди, сначала делаем проверку с помощью isset() , затем с помощью array_key_exists() . Ключ, наличие которого проверяем, генерируется случайным образом, чтобы свести к минимуму вероятность его существования в массиве.

isset() array_key_exists() 0.687027 0.728652

Тест, безусловно, очень простой и достаточно субъективный. Было бы неплохо сделать замеры используемой памяти, например. Но глядя на результаты этого теста, у меня нет никакого желания продолжать заниматься мышиной возней. Очевидно, что выигрыша в скорости попросту нет.

Функция isset() и свойства объекта

Совсем клиническим случаем можно считать использование isset() для проверки существования свойства у объекта.

Не так часто, как в случае с массивами, но доводится встречать подобные условия:

Случай вопиющий, так как использование NULL в качестве дефолтного значения свойств – очень распространенная практика. И проверять наличие свойства объекта через isset() просто недопустимо.

Для проверки существования свойства у объекта в PHP существует функция property_exists() . Как и array_key_exists() , property_exists() вернет TRUE даже в том случае, если значение свойства приведено к NULL.

Также замечу, что для использования property_exists() не требуется наличие объекта класса. Проверку можно произвести по имени класса и имени свойства.

Такое вот занимательное программирование.

Комментарии (6)

Вечер добрый! Очень классные статьи, большое спасибо за них!

Насчет функции isset. А если такой случай — есть функция getUsers($data), которая возвращает пользователей из БД. Если передано значение $data[‘where’] (ассоциативный массив по которому происходит фильтрация), то произвести фильтрацию. У меня в коде if (isset($data[‘where’])), в данном случае я верно пишу? Т.к. мне нужно знать не только существует ли ключ но так же чтобы у него было значение. (Кстати, тогда даже наверно if (is_array($data[‘where’])) т.к. ф-ии нужно передавать именно ассоциативный массив)

Вы все верно поняли. На самом деле, практически повсеместно используется isset(). Иногда из-за этого возникают логические ошибки в приложениях, что и стало причиной написания данной заметки.

Не надо людей вводить в заблуждение и навязывать свои ошибочные мысли. В мануале от создателей PHP явно сказано, что isset используется и для проверки элементов массива. И это правильно. А вот использовать элемент массива с NULL и считать этот элемент существующим, это ошибка. Вот из-за таких как ты и приходится потом сутками сидеть и разгребать больные коды и не понимать, почему же блин переменные NULL существуют.

Максим, во-первых, я вам вам не «ты». А во-вторых, мир сложнее, чем вам кажется и нужно беречь свои нервы, а то не хватит сил на разгребание больных кодов :)) И если NULL значение в массиве — это ошибка, то это ошибка в интерпретаторе PHP. Но, думаю, дело все в том, что вы просто не понимаете смысл типа данных NULL.

Олег, вы не правы в ряде моментов. Не стоит «гнать» на PHP разработчиков, т.к. те кто ними являются, пишут хороший код. А то, что вы всех, кто написал строчку кода на PHP называете PHP-программистом, это лично ваши «психо-половые» проблемы. Второй момент, насчет NULL: в языке PHP смысл языковой конструкции null отличается от той же конструкции SQL … и не стоит и пытаться друг на друга «натягивать». Это не проблема языка, т.к. авторы языка вольны толковать как им вздумается «сколько людей, столько и мнений.». Третий момент, если Вы знаете, что PHP-разработчики пишут плохой код, то зачем вы его используете? Пишите сами или используете код других языков. Я могу понять, что писали вы пост под влиянием эмоций, но я так и не понял, что было не так в том коде «китайского движка» и что у вас не выходило? :) Напишите название движка, чтобы люди знали о том, и что тут могут вылезти проблемы при использовании и место возникновения проблемы.

📎📎📎📎📎📎📎📎📎📎