«Примечание: неопределенная переменная», «Примечание: неопределенный индекс» и «Примечание: неопределенное смещение» с использованием PHP - PullRequest
1096 голосов
/ 24 ноября 2010

Я запускаю 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"];

Что означают эти сообщения об ошибках?

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

Как мне их исправить?

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

Связанная мета-дискуссия:

Ответы [ 28 ]

1001 голосов
/ 24 ноября 2010

Примечание: неопределенная переменная

Из обширной мудрости PHP Manual :

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

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

Предупреждение не генерируется, если переменная не существует. Это означает empty () является кратким эквивалентом ! Isset ($ var) || $ вар == false .

Это означает, что вы можете использовать только empty(), чтобы определить, установлена ​​ли переменная, и, кроме того, она проверяет переменную по следующим параметрам: 0, 0.0, "", "0", null, false или [].

* * Пример 1 042:

$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";
});

Проверьте приведенный выше фрагмент в онлайн-редакторе 3v4l.org

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

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

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

    //Initializing variable
    $value = ""; //Initialization value; Examples
                 //"" When you want to append stuff later
                 //0  When you want to add numbers later
    //isset()
    $value = isset($_POST['value']) ? $_POST['value'] : '';
    //empty()
    $value = !empty($_POST['value']) ? $_POST['value'] : '';
    

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

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
    
  2. Установить пользовательский обработчик ошибок для E_NOTICE и перенаправить сообщения из стандартного вывода (возможно, в файл журнала):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
    
  3. Отключить E_NOTICE от создания отчетов. Быстрый способ исключить только E_NOTICE:

    error_reporting( error_reporting() & ~E_NOTICE )
    
  4. Устранить ошибку с помощью оператора @ .

Примечание: Настоятельно рекомендуется реализовать только пункт 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'] : '';
    
  2. Языковая конструкция list() может генерировать это при попытке доступа к индексу массива, который не существует:

    list($a, $b) = array(0 => 'a');
    //or
    list($one, $two) = explode(',', 'test string');
    

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

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

$_POST / $_GET / $_SESSION переменная

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

Также обратите внимание, что все 3 переменные суперглобальные и прописные.

Связанный:

129 голосов
/ 24 ноября 2010

Попробуйте это

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

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

// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? '';

// pre-7 PHP versions
$user_name = '';
if (!empty($_SESSION['user_name'])) {
     $user_name = $_SESSION['user_name'];
}

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

// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);

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

60 голосов
/ 24 ноября 2010

Отображение ошибки @ оператор

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

$var = @($_GET["optional_param"]);
  • Обычно это не рекомендуется.Новички склонны злоупотреблять им.
  • Это очень неуместно для кода глубоко внутри логики приложения (игнорируя необъявленные переменные, где вы не должны), например, для параметров функции или в циклах.
  • Естьоднако один перевес над суперподавлением isset?: или ??.Уведомления все еще могут быть зарегистрированы.И можно воскресить @ скрытые уведомления с помощью: set_error_handler("var_dump");
    • Кроме того, вы не должны обычно использовать / рекомендовать if (isset($_POST["shubmit"])) в своем исходном коде.
    • Новички не заметят такихопечаток.Это просто лишает вас уведомлений PHP для тех самых случаев.Добавьте @ или isset только после проверки работоспособности.
    • Сначала устраните причину.Не уведомления.

  • @ в основном приемлемо для $_GET / $_POST входных параметров, в частности , еслиони являются необязательными .

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

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

  • Первое, что вы делаете при обнаружении неопределенного индекса / смещения, это проверка на опечатки:
    $count = $_GET["whatnow?"];

    • Этоожидаемое имя ключа и присутствующее на каждом запросе страницы?
    • Имена переменных * Индикаторы массива и чувствительны к регистру в PHP.
  • Во-вторых, если в уведомлении нет явной причины, используйте var_dump или print_r, чтобы проверить все входные массивыдля их текущего содержания:

    var_dump($_GET);
    var_dump($_POST);
    //print_r($_REQUEST);
    

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

  • Альтернативно или дополнительно используйтеВаш браузер devtools ( F12 ) и проверьте вкладку сети на наличие запросов и параметров:

    browser developer tools / network tab

    POSTпараметры и вход GET будут показаны отдельно.

  • Для параметров $_GET вы также можете посмотреть на QUERY_STRING в

    print_r($_SERVER);
    

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

  • Более очевидно, посмотрите в адресной строке вашего браузера GET-параметры :

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

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

  • Наконец, проверьте ваши объявления <form> и <input>, если вы ожидаете параметрно не получают.

    • Убедитесь, что на каждом необходимом входе есть <input name=FOO>
    • Атрибут id= или title= не достаточен.
    • A method=POST форма должна заполняться $_POST.
    • Принимая во внимание, что method=GET (или исключение из нее) даст $_GET переменных.
    • Форма также может предоставить action=script.php?get=paramчерез $ _GET и оставшиеся method=POST поля в $ _POST вместе с
    • С современными конфигурациями PHP (≥ 5.6) стало выполнимым (не модно) использовать $_REQUEST['vars'] снова, что смешивает параметры GET и POST.
  • Если вы используете mod_rewrite, то вы должны проверить как access.log, так и включить RewriteLog, чтобы выяснить отсутствующие параметры.

$_FILES

  • Те же проверки работоспособности применяются к file загружает и $_FILES["formname"].
  • Более того, проверьте enctype=multipart/form-data
  • , а также method=POST в вашей декларации <form>.
  • См. также: PHP Неопределенная ошибка индекса $ _FILES?

$_COOKIE

  • Массив $_COOKIE никогда не заполняется сразу после setcookie(), а только при любом последующем HTTP-запросе.
  • Кроме того, срок их действия истекает, они могут быть ограничены поддоменами или отдельными путями, а пользователь и браузер могут просто отклонить или удалить их.
44 голосов
/ 24 ноября 2010

Обычно из-за «плохого программирования» и возможности ошибок сейчас или позже.

  1. Если это ошибка, сначала сделайте правильное присвоение переменной: $ varname = 0;
  2. Если это действительно только иногда определяется, проверьте его: if (isset($varname)), прежде чем использовать его
  3. Если это потому, что вы написали это неправильно, просто исправьте это
  4. Возможно, даже поворотпредупреждения у вас PHP-настройки
40 голосов
/ 24 ноября 2010

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

34 голосов
/ 30 декабря 2011

Я не хотел отключать уведомление, потому что это полезно, но хотел избежать слишком большого количества печатания.

Мое решение было этой функцией:

function ifexists($varname)
{
  return(isset($$varname)?$varname:null);
}

Так что, если я хочу сослаться на $ name и echo, если существует, я просто пишу:

<?=ifexists('name')?>

Для элементов массива:

function ifexistsidx($var,$index)
{
  return(isset($var[$index])?$var[$index]:null);
}

На странице, если я хочу сослаться на $ _REQUEST ['name']:

<?=ifexistsidx($_REQUEST,'name')?>
26 голосов
/ 27 августа 2014

Лучший способ получения ввода string :

$value = filter_input(INPUT_POST, 'value');

Этот однострочный почти эквивалентен:

if (!isset($_POST['value'])) {
    $value = null;
} elseif (is_array($_POST['value'])) {
    $value = false;
} else {
    $value = $_POST['value'];
}

Если вы абсолютно хотите строка значение, как:

$value = (string)filter_input(INPUT_POST, 'value');
25 голосов
/ 29 декабря 2012

Это потому, что переменная '$ 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;
25 голосов
/ 23 ноября 2016

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

Для большинства сайтов очень распространено использование отчетов об ошибках по умолчанию" Показать все ошибки, ноне «уведомления» и «не рекомендуется». Это будет установлено в php.ini и будет применяться ко всем сайтам на сервере. Это означает, что те «уведомления», используемые в примерах, будут подавлены (скрыты), в то время как другие ошибки считаются болеекритический, будет показан / записан.

Другой критический параметр - ошибки, которые могут быть скрыты (т. е. display_errors установлен на «выключен» или «системный журнал»).

Что произойдетв этом случае либо error_reporting был изменен для отображения уведомлений (согласно примерам), и / или что настройки были изменены на display_errors на экране (в отличие от их подавления / регистрации).

Почему они изменились?

Очевидный / самый простой ответ заключается в том, что кто-то изменил эти настройки в php.ini, или обновленная версия PHP теперь использует другой php.Ини из befруды.Это первое место для поиска.

Однако также можно переопределить эти настройки в

  • .htconf (конфигурация веб-сервера, включая vhosts и субконфигурации) *
  • .htaccess
  • в самом коде php

, и любой из них также может быть изменен.

Существует также дополнительное осложнение, что конфигурация веб-сервераМожно включить / отключить директивы .htaccess, поэтому если у вас есть директивы в .htaccess, которые внезапно начинают / перестают работать, вам нужно проверить это.

(. htconf / .htaccess предполагает, что вы работаете как apache.Если для командной строки это не применимо, для IIS или другого веб-сервера вам необходимо соответствующим образом проверить эти конфигурации)

Сводка

  • ПроверкаДирективы error_reporting и display_errors php в php.ini не изменились, или что вы не используете другой php.ini, из которого были раньше.
  • Проверьте error_reporting и display_errors директивы php в.htconf (или vhosts и т. д.) имеютне изменилось
  • Проверьте, что директивы error_reporting и display_errors php в .htaccess не изменились
  • Если у вас есть директива в .htaccess, проверьте, разрешены ли они в файле .htconf
  • Наконец, проверьте ваш код;возможно несвязанная библиотека;чтобы увидеть, были ли там установлены директивы error_reporting и display_errors php.
20 голосов
/ 12 мая 2014

быстрое решение - присвоить переменной значение NULL в верхней части кода

$user_location = null;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...