Web

Почему происходит «Неопределенная переменная/индекс/смещение» в PHP

Я запускаю PHP-скрипт и получаю ошибки типа:

Примечание: Неопределенная переменная: my_variable_name в C:\wamp\www\mypath\index.php на строке 10

Примечание: Неопределенный индекс: my_index C:\wamp\www\mypath\index.php в строке 11

Строки 10 и 11 выглядят следующим образом:

echo "My variable value is: " . $my_variable_name;

echo "My index value is: " . $my_array["my_index"];

В чем смысл этих сообщений об ошибках? Почему они вдруг стали появляться? Я использовал этот скрипт в течение многих лет, и у меня никогда не было никаких проблем. Как мне их устранить?

 

Ответ 1

Уведомление: Неопределенная переменная

Из руководства по PHP:

Полагаться на значение по умолчанию неинициализированной переменной проблематично в случае включения одного файла в другой, который использует то же имя переменной. Это также является серьезным риском безопасности при включенном register_globals. Ошибка уровня E_NOTICE выдается в случае работы с неинициализированными переменными, но не в случае добавления элементов в неинициализированный массив. Языковая конструкция isset() может быть использована для определения того, была ли переменная уже инициализирована. Кроме того, более идеальным является решение empty(), поскольку оно не выдает предупреждение или сообщение об ошибке, если переменная не инициализирована.

Из документации PHP:

Если переменная не существует, предупреждение не выдается. Это означает, что empty() по сути является кратким эквивалентом !isset($var) || $var == false. Это значит, что вы можете использовать только empty() для определения того, установлена ли переменная, и, кроме того, она проверяет переменную на соответствие следующим значениям: 0, 0.0, "", «0», null, false или [].

Пример:

$o = [];

@$var = ["",0,null,1,2,3,$foo,$o['myIndex']];

array_walk($var, function($v) {

    echo (!isset($v) || $v == false) ? 'true ' : 'false';

    echo ' ' . (empty($v) ? 'true' : 'false');

    echo "\n";

});

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

Способы решения проблемы:

  1. Объявляйте свои переменные, например, когда вы пытаетесь добавить строку к неопределенной переменной. Или используйте isset()/!empty(), чтобы проверить, объявлены ли они, прежде чем ссылаться на них, как в примере:

// инициализация переменной

$value = ""; // инициализация значения

                    // "" Когда вы хотите добавить материал позже

                   // 0 Когда вы хотите добавить числа позже//isset()

$value = isset($_POST['value']) ? $_POST['value'] : '';

//empty()

$value = !empty($_POST['value']) ? $_POST['value'] : '';

 Начиная с PHP 7.0 это стало намного проще, теперь вы можете использовать оператор null coalesce:

// Оператор Null coalesce - Нет необходимости явно инициализировать переменную.

$value = $_POST['value'] ?? '';

  1. Установите пользовательский обработчик ошибок для E_NOTICE и перенаправьте сообщения из стандартного вывода (возможно, в файл журнала):

set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT).

  1. Исключите E_NOTICE из отчетов. Быстрый способ исключить только E_NOTICE это:

error_reporting( error_reporting() & ~E_NOTICE ).

  1. Подавите ошибку с помощью оператора «@».

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

 

Уведомление: Неопределенный индекс/Неопределенное смещение

Это уведомление появляется, когда вы (или PHP) пытаетесь получить доступ к неопределенному индексу массива.

Способы решения проблемы:

  1. Проверьте, существует ли индекс, прежде чем обращаться к нему. Для этого можно использовать isset() или array_key_exists():

//isset()

$value = isset($array['my_index']) ? $array['my_index'] : '';

//array_key_exists()

$value = array_key_exists('my_index', $array) ? $array['my_index'] : '';

  1. Языковая конструкция list() может выдать такую ошибку, когда пытается получить доступ к несуществующему индексу массива:

list($a, $b) = array(0 => 'a');

//или

list($one, $two) = explode(',', 'test string');

Две переменные используются для доступа к двум элементам массива, однако существует только один элемент массива, индекс 0, поэтому будет сгенерировано следующее:

Примечание: Неопределенное смещение: 1

 

Переменные $_POST/$_GET/$_SESSION

Приведенные выше уведомления часто появляются при работе с $_POST, $_GET или $_SESSION. Для $_POST и $_GET нужно просто проверить, существует ли индекс или нет, прежде чем использовать их. Для $_SESSION необходимо убедиться, что сессия запущена с помощью session_start() и что индекс также существует. Также обратите внимание, что все три переменные являются суперглобалами и написаны в верхнем регистре.

 

Ответ 2

Попробуйте следующее:

Q1: это уведомление означает, что $varname не определена в текущей области видимости скрипта.

Q2: использование условий isset(), empty() перед использованием любой подозрительной переменной работает хорошо.

// рекомендуемое решение для последних версий PHP

$user_name = $_SESSION['user_name'] ?? '';

 

// до 7 версии PHP

$user_name = '';

if (!empty($_SESSION['user_name'])) {

     $user_name = $_SESSION['user_name'];

}

Или, как быстрое и простое решение:

// не лучшее решение, но работает

// в ваших настройках php, это помогает скрыть уведомления по всему сайту

error_reporting(E_ALL ^ E_NOTICE);

 

Примечание о сессиях:

  1. При использовании сессий, session_start(); необходимо размещать внутри всех файлов, использующих сессии.

  2. См. http://php.net/manual/en/features.sessions.php

 

Ответ 3

Оператор «@» для отображения ошибок.

 Для нежелательных и избыточных уведомлений можно использовать специальный оператор «@», чтобы «скрыть» сообщения о неопределенных переменных/индексах.

$var = @($_GET["optional_param"]);

Замечания:

  1. Обычно это не рекомендуется. Новички склонны злоупотреблять им.

  2. Это очень неуместно для кода, находящегося глубоко в логике приложения (игнорирование необъявленных переменных там, где этого делать не следует), например, для параметров функций или в циклах.

  3. Однако есть один плюс по сравнению с суперсупрессией isset(: или ??). Уведомления все еще могут быть зарегистрированы. И можно восстановить «@»-скрытые уведомления с помощью: set_error_handler("var_dump");

  4. Кроме того, не стоит привычно использовать/рекомендовать if (isset($_POST["shubmit"])) в начальном коде.

  5. Новички не заметят таких опечаток. Это просто лишает вас уведомлений PHP именно для таких случаев. Добавляйте «@» или isset только после проверки функциональности.

  6. Сначала устраните причину, а не уведомления.

  7. «@» в основном допустимо для входных параметров $_GET/$_POST, особенно если они необязательны.

И поскольку это охватывает большинство подобных вопросов, давайте остановимся на наиболее распространенных причинах:

 

Неопределенный ввод $_GET/$_POST/$_REQUEST

  1. Первое, что вы делаете, когда сталкиваетесь с неопределенным индексом/смещением, это проверяете опечатки:

$count = $_GET["whatnow?"];

  1. Является ли это ожидаемым именем ключа и присутствует ли оно в каждом запросе страницы?

  2. Имена переменных и индексы массивов чувствительны к регистру в PHP.

  3. Во-вторых, если уведомление не имеет очевидной причины, используйте var_dump или print_r для проверки всех входных массивов на их текущее содержимое:

var_dump($_GET);

var_dump($_POST);

//print_r($_REQUEST);

Оба способа покажут, был ли ваш скрипт вызван с правильными параметрами или вообще без параметров.

  1. Альтернативно или дополнительно используйте devtools вашего браузера (F12) и просмотрите вкладку network на предмет запросов и параметров

  2. Для параметров $_GET вы также можете заглянуть в QUERY_STRING в разделе

print_r($_SERVER);

PHP имеет некоторые правила для объединения нестандартных имен параметров в суперглобалы. Apache также может переписать некоторые имена. Вы также можете посмотреть на необработанные $_COOKIES и другие заголовки HTTP-запросов.

  1. Более очевидный способ посмотреть в адресной строке браузера параметры GET:

http://example.org/script.php?id=5&sort=desc

  1. Пары имя=значение после вопросительного знака «?»  являются параметрами вашего запроса (GET). Таким образом, этот URL может дать только $_GET["id"] и $_GET["sort"].

  2. Наконец, проверьте декларации <form> и <input>, если вы ожидаете параметр, но не получаете его.

  1. Убедитесь, что каждый требуемый вход имеет <input name=FOO>.

  2. Атрибута id= или title= недостаточно.

  3. Форма method=POST должна заполнять $_POST.

  4. В то время как метод=GET (или его отсутствие) приведет к появлению переменных $_GET.

  5. Также возможно, чтобы форма передавала action=script.php?get=param через $_GET, а остальные поля method=POST в $_POST рядом.

  6. В современных конфигурациях PHP (≥ 5.6) стало возможным (не модным) снова использовать $_REQUEST['vars'], который объединяет GET и POST параметры.

  1. Если вы используете mod_rewrite, то вам следует проверить как access.log, так и включить RewriteLog, чтобы выяснить отсутствующие параметры.

 

$_FILES

  1. Те же проверки на корректность применяются к загрузке файлов и $_FILES["formname"].

  2. Кроме того, проверьте наличие enctype=multipart/form-data

  3. а также method=POST в объявлении <form>.

  4. Смотрите также: PHP Ошибка неопределенного индекса $_FILES

 

$_COOKIE

  1. Массив $_COOKIE никогда не заполняется сразу после setcookie(), а только при любом последующем HTTP-запросе.

  2. Кроме того, их срок действия истекает, они могут быть ограничены поддоменами или отдельными путями, и пользователь, и браузер могут просто отклонить или удалить их.

 

Ответ 4

Это происходит потому, что переменная '$user_location' не определяется. Если вы используете какой-либо цикл if, внутри которого вы объявляете переменную '$user_location', то вы также должны иметь цикл else и определить ее. Например:

$a=10;

if($a==5) { $user_location='Paris';} else { }

echo $user_location;

Приведенный выше код приведет к ошибке, поскольку цикл if не завершен, а в цикле else '$user_location' не был определен. Тем не менее, для PHP было предложено вывести переменную эхом. Поэтому, чтобы изменить код, необходимо сделать следующее:

$a=10;

if($a==5) { $user_location='Paris';} else { $user_location='SOMETHING OR BLANK'; }

echo $user_location;

 

Схожие статьи

Web

Отладка проблем с функцией exec

Web

Как восстановить сериализованную строку, которая была повреждена из-за неправильной длины счетчика байтов

Web

Функция PHP для генерации UUID v4

Web

isset() и empty() - что лучше использовать?

×