PHP Notice:  Undefined variable: inactive_sohps in /app/cottenio/core.php on line 567

PHP чрезвычайно снисходителен к неопределенным переменным, в отличие от языков со статической типизацией, таких как C.

На самом деле настолько допустимо, что неопределенная переменная классифицируется не на уровне Error или Warning, а вместо этого на уровне Notice.

Почему?

Потому что неопределенная переменная в PHP временно заменяется значением по умолчанию, если она еще не была назначена¹.

Как работают неопределенные переменные

Во-первых, как нам доказать, что интерпретатор PHP выполняет только временную замену? Откуда мы знаем, что он не инициализирует переменную своим значением по умолчанию после первой встречи с ней?

Приведенный выше код вызывает переменную $r дважды: один раз в строке 2, второй раз в строке 4.

Если бы интерпретатор сделал что-нибудь с $r, кроме простой замены его — в момент использования — предполагаемым значением по умолчанию, например, инициализацией его фактическим значением по умолчанию, тогда мы бы узнать по второму звонку.

PHP Notice:  Undefined variable: r in /app/cottenio/php/1.php on line 2
PHP Notice:  Undefined variable: r in /app/cottenio/php/1.php on line 4

Но нет, как мы видим в выводе журнала, он распознает, что $r все еще не определено в строке 4, хотя интерпретатор что-то сделал с ним в строке 2.

Но подождите, как интерпретатор узнает, какое «значение по умолчанию» использовать?

По правде говоря, эта идея «значения по умолчанию» для неопределенной переменной является неправильным. Вы можете подумать, что он использует пустую строку при анализе strlen() или что она равна нулю при использовании floor() — но на самом деле?

Это просто NULL.

Функции и операторы PHP, конечно же, должны обрабатывать значение NULL так, как если бы оно было соответствующим «ложным» эквивалентом, таким образом создавая иллюзию осведомленности о контексте.

Для strlen() это пустая строка, как если бы вы передали "", или для floor() она оценивается как 0.

Вот почему мы говорим, что PHP — такой щадящий язык для веб-разработки: он позволяет вам незаметно сбой во многих случаях, который в языках со статической типизацией привел бы к возникновению исключения или фатальной ошибки.

Поведение неопределенных переменных

Давайте рассмотрим это поведение дальше на простом примере. Например, предположим, что вы строите строку на основе содержимого цикла, например:

Цель скрипта — распечатать строку $str, содержащую текст "1 2 3 4 5 6 7 8 9 ", что он делает без проблем.

Однако, когда отчет об ошибках E_ALL включен, он также генерирует событие E_NOTICE, например:

PHP Notice:  Undefined variable: str in /app/cottenio/php/1a.php on line 3

В первый раз, когда оператор присваивания конкатенации² сталкивается с $str, переменная не была определена ранее, поэтому он использует возможность инициализировать ее как пустую строку, а затем добавить в нее содержимое "{$i} ".

Решение, конечно же, простое:

Добавив $str = ""; перед циклом, мы заявили о своем намерении интерпретатору PHP, и теперь оператор присваивания конкатенации не должен выдавать Notice в журнал.

Орфографические ошибки — бич отладки

Еще один аспект регистрации уведомлений для неопределенных переменных заключается в том, что это хороший способ найти переменные с ошибками, если они каким-то образом ускользают от вас или вашей IDE.

Например:

PHP Notice:  Undefined variable: inactive_sohps in /app/cottenio/core.php on line 18

Возможно, функциональность рассматриваемого проекта не казалась затрудненной с точки зрения пользователей, но у вас есть Notice в журнале. Изучите следующее:

Цель приведенного выше кода — собрать список всех $shops (местоположений магазинов), которые имеют различные атрибуты. Если им не 'active', их следует занести в ручной список контактов (если у них установлен номер телефона 'phone_no'), чтобы служба поддержки могла позвонить им и выяснить, почему они не в сети.

Это крошечная часть гораздо более крупной информационной панели, отвечающей за повседневную деятельность агентов по обслуживанию клиентов.

А теперь представьте ваше удивление после развертывания кода, когда отдел обслуживания клиентов радостно сообщает: «Вау, похоже, все магазины снова открываются! Сегодня нам не пришлось никому звонить, чтобы проверить их статус!»

Такие хорошие новости во время закрытия магазинов, связанных с COVID-19?

Нет. Вероятно, что-то не так с кодом.

При проверке журналов вы бы быстро увидели переменную undefined и поняли, что это было вызвано опечаткой, но эй: с PHP все было в порядке. Поскольку переменной не существовало, она создала ее и передала NULL функции empty().

Таким образом, условие оценивается как false и пропускается логика создания списка контактов.

PHP, будучи подозрительным, по крайней мере отправил уведомление в журнал, но в остальном с радостью отрендерил все остальные части вашего теоретического проекта без жалоб.

Операции с массивами

Кстати, вы заметили строку 8 в предыдущем примере?

$inactive_shops[] = $shop;

Поскольку массив $inactive_shops не определен перед циклом foreach, вы можете подумать, что он будет генерировать Notice каждый раз при выполнении этого блока или, что еще хуже, во время выполнения каждого цикла.

Но нет, по определению, неопределенные переменные НЕ будут генерировать событие E_NOTICE, если это присваивание массива³ с использованием оператора [], даже в сокращенной версии присваивания, такой как $inactive_shops[], которая просто добавляет входящее присваивание в конец массива.

В этом случае он фактически инициализирует переменную как массив и без проблем добавляет к ней правое значение.

Данглерс

Иногда код очищается и редактируется, оставляя после себя переменную, которая, хотя и не используется, все же оценивается в какой-то момент выполнения.

Эти висячие переменные отображаются, конечно, как неопределенные переменные — это означает, что вам нужно вернуться и очистить их (или предоставить соответствующие замены!)

Вывод

Вам нужно было еще одно обоснование для включения ведения журнала предупреждений/уведомлений даже в рабочей среде? Надеюсь, что нет, но если да, то вот!

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

использованная литература

[1] https://stackoverflow.com/questions/12769982/reference-what-does-this-error-mean-in-php/12778634#12778634

[2] https://www.php.net/manual/en/language.operators.php

[3] https://www.php.net/manual/en/language.variables.basics.php