«Примечание: неопределенная переменная», «Примечание: неопределенный индекс» и «Примечание: неопределенное смещение» с использованием PHP

1175

Я запускаю сценарий 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"];

В чем смысл этих сообщений об ошибках?

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

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


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

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

Pekka 웃
источник
8
Возможный дубликат ссылки. Что означает эта ошибка в PHP?
Meagar
3
переменная, возможно, не была инициализирована. Вы инициализируете переменную из записи, получения или любого массива? Если это так, у вас может не быть поля в этом массиве. Это твой доступ.
Аниш Силвал
3
@Pekka 웃 - я заметил, что редактирование добавило «и« Уведомление: неопределенное смещение »» - Разве это не имеет смысла, используя «PHP:« Неопределенная переменная »,« Неопределенный индекс »,« Неопределенное смещение »» (даже из PHP, так как он помечен как "php". Плюс, URL обрезается and-notice-undef, просто предложение, чтобы URL не обрезался. Возможно, даже удаляя (слишком много) кавычек. ИлиPHP: “Undefined variable/index/offset” notices
Funk Forty Девятого
2
@ Фред Я думаю, что аргументы могут быть сделаны для обоих вариантов. Существует вероятность того, что новички введут всю строку, включая «Уведомление», в свой поисковый запрос, который, я уверен, является основным генератором трафика для этого вопроса. Если сообщения там есть полностью, это, вероятно, улучшит видимость в поисковых системах
Пекка
2
@ Пекка 웃 Я понимаю. Я только сказал это, потому что URL не был обрезан раньше, а теперь это происходит в and-notice-undef. Это было всего лишь (несколько) предложений. Это просто повторяет себя и быть Notice: Undefined.
Funk Forty

Ответы:

1067

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

Из огромной мудрости руководства по 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 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 переменные являются суперглобальными и имеют прописные буквы.

Связанные с:

Rizier123
источник
7
@ dieselpower44 Несколько мыслей: у «оператора затвора» ( @) есть некоторые проблемы с производительностью. Кроме того, поскольку он подавляет все ошибки в определенной области, его использование без осторожности может маскировать сообщения, которые вы хотели бы видеть.
IMSoP
6
Сокрытие проблем не является способом решения проблем. Элементы № 2 ... № 4 могут использоваться только на производственных серверах, но не в целом.
Салман,
1
Можно ли отключить встроенное сообщение (не в обработчике), когда также используется специальный обработчик ошибок? $var = @$_GET['nonexisting'];все еще вызывает уведомление ..
Alph.Dev
18
Почему рекомендуется использовать 1. $value = isset($_POST['value']) ? $_POST['value'] : '';вместо 4. $value = @$_POST['value'];?
forsvunnet
@twistedpixel Эти 4 способа независимы, это не руководство из 4 шагов. Поэтому, если вы выбрали способ 4, это означает, что вы не реализовали первые 3 способа, поэтому вы еще не подавили никаких ошибок.
Айкан Яшит
141

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

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);

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

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

  • http://php.net/manual/en/features.sessions.php

Ish
источник
При использовании E_NOTICEиз php.iniфайла конфигурации, сделайтеerror_reporting = (E_ALL & ~E_NOTICE)
ahmd0
Из приведенного выше ответа я попробовал isset, array_key_exists, но они не сработали. Я попробовал ваш ответ, .empty (), и он работает. Большое спасибо!
ewef
63

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

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

$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) и проверьте вкладку сети на наличие запросов и параметров:

    инструменты разработчика браузера / вкладка сети

    Параметры 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=атрибут не хватает.
    • 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

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

$_COOKIE

  • $_COOKIEМассив никогда не заполняется сразу после setcookie(), но только на любой запрос HTTP Followup.
  • Кроме того, срок их действия истекает, они могут быть ограничены поддоменами или отдельными путями, и пользователь и браузер могут просто отклонить или удалить их.
марио
источник
2
Если вам интересно, как это влияет на производительность, эта статья хорошо ее обобщает, derickrethans.nl/… .
Gajus
@GajusKuizinas С 2009 года произошло несколько изменений, в частности php.net/ChangeLog-5.php#5.4.0 радикально изменил результат (см. «Оператор Zend Engine, производительность» и «Оператор молчания»).
Марио
Спасибо @mario, интересно. Теперь, если кто-то был достаточно хорош для сравнения двух ... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs В соответствии с этим тестом, похоже, идентичны (обратите внимание, что масштаб изменяется).
Gajus
47

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

  1. Если это ошибка, сначала сделайте правильное присвоение переменной: $ varname = 0;
  2. Если это действительно только иногда определяется, проверьте его: if (isset($varname))перед использованием
  3. Если это потому, что вы написали это неправильно, просто исправьте это
  4. Может быть, даже череда предупреждений в ваших PHP-настройках
Erik
источник
5
Пожалуйста, не выключайте предупреждения. В более строгих языках они часто означают «может быть ошибка, лучше проверить эту строку дважды» - на языке, столь же допустимом, как PHP, они часто означают «этот код дерьмов и, вероятно, изобилует ошибками; я постараюсь сделать какой-то смысл, но вам лучше исправить это как можно скорее ".
5
Хотя я согласен с первыми тремя пунктами, № 4 просто ошибочен. Сокрытие проблемы не заставит ее исчезнуть, и это может даже вызвать больше проблем в будущем.
Валентин Флаксель
1
@ Правда, правда, но в некоторых сценариях (купленный сценарий, ноль технических знаний, нужно ли его запустить к завтрашнему дню ...) это решение на основе клейкой ленты - действительно плохо, которое всегда нуждается в подчеркивании, но вариант
Pekka
Липкая лента хороша ... иногда. Исторически предупреждения были отключены в стандартных настройках PHP, но настройки по умолчанию стали более строгими. Жаль, что многие возвращаются к старым настройкам, чтобы не раздражать клиентов.
Эрик
41

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

DGM
источник
34

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

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

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')?>
Ференци Золтан Ласло
источник
2
Ваша функция ifexists () не работает для меня в PHP 5.3. Переменные вызывающей стороны недоступны в локальной области действия функции (см. Область переменных ), если только они не являются суперглобальными или вы не играете с $ GLOBALS , поэтому $foo = "BABAR"; ifexists('foo');в общем случае будет возвращать ноль. (Курсивом являются главы php.net.)
skierpage
теперь вы получите "привет от" ... какой смысл? просто проверьте значениеif( !empty($user) and !empty($location) ) echo "hello $user ..."
gcb
27

Лучший способ получить входную строку :

$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');
mpyw
источник
25

Это потому, что переменная '$ 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;
Roger
источник
25

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

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

Другая критическая настройка - ошибки могут быть скрыты (т.е. display_errors Установлены на «off» или «syslog»)

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

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

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

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

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

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

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

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

Резюме

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

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

$user_location = null;
Шахин Мамедзада
источник
16

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

Например, если вы думали, что это умный, сокращенный код:

// Echo whatever the hell this is
<?=$_POST['something']?>

... подумай еще раз! Лучшее решение:

// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>

(Я использую пользовательскую html()функцию для экранирования символов, ваш пробег может отличаться)

rybo111
источник
15

В PHP 7.0 теперь можно использовать оператор объединения нулей:

echo "My index value is: " . ($my_array["my_index"] ?? '');

Равно:

echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');

Руководство по PHP PHP 7.0

elpiel
источник
Это также хорошо работает в операторах if. if (is_array($my_array['idontexist'] ?? '')) { dosomething(); }
кодер
Ваш код на самом деле является хорошей ошибкой: - только проверяет isset(), если вы передадите is_array()- что является логическим значением, последует неожиданное поведение.
elpiel
14

Я все время использую собственную полезную функцию exst (), которая автоматически объявляет переменные.

Ваш код будет -

$greeting = "Hello, ".exst($user_name, 'Visitor')." from ".exst($user_location);


/** 
 * Function exst() - Checks if the variable has been set 
 * (copy/paste it in any place of your code)
 * 
 * If the variable is set and not empty returns the variable (no transformation)
 * If the variable is not set or empty, returns the $default value
 *
 * @param  mixed $var
 * @param  mixed $default
 * 
 * @return mixed 
 */

function exst( & $var, $default = "")
{
    $t = "";
    if ( !isset($var)  || !$var ) {
        if (isset($default) && $default != "") $t = $default;
    }
    else  {  
        $t = $var;
    }
    if (is_string($t)) $t = trim($t);
    return $t;
}
оборота user2253362
источник
14

На очень простом языке .
Ошибка в том, что вы используете переменную, $user_locationкоторая не была определена ранее и не имеет никакого значения. Поэтому я рекомендую вам объявить эту переменную перед ее использованием , например:


$user_location = '';
Или
$user_location = 'Los Angles';
Это очень распространенная ошибка, с которой вы можете столкнуться. Так что не волнуйтесь, просто объявите переменную и наслаждайтесь кодированием .

Ришабх Сет
источник
8

почему бы не сделать вещи простыми?

<?php
error_reporting(E_ALL); // making sure all notices are on

function idxVal(&$var, $default = null) {
         return empty($var) ? $var = $default : $var;
  }

echo idxVal($arr['test']);         // returns null without any notice
echo idxVal($arr['hey ho'], 'yo'); // returns yo and assigns it to array index, nice

?>
ГСТ
источник
8

ПОЧЕМУ ЭТО ПРОИСХОДИТ?

Со временем PHP стал более ориентированным на безопасность языком. Настройки, которые раньше были отключены по умолчанию, теперь включены по умолчанию. Прекрасный пример этого E_STRICT, который стал включенным по умолчанию с PHP 5.4.0 .

Кроме того, согласно документации PHP, по умолчанию E_NOTICEотключен в php.ini. Документы PHP рекомендуют включать его в целях отладки . Однако, когда я загружаю PHP из репозитория Ubuntu - и из стека Windows BitNami - я вижу что-то еще.

; Common Values:
;   E_ALL (Show all errors, warnings and notices including coding standards.)
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

Обратите внимание, что error_reportingпо умолчанию установлено производственное значение, а не значение по умолчанию. Это несколько сбивает с толку и не документировано за пределами php.ini, поэтому я не проверял это в других дистрибутивах.

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

  1. Вы установили PHP, и новые настройки по умолчанию несколько плохо документированы, но не исключают E_NOTICE.

  2. E_NOTICEпредупреждения, такие как неопределенные переменные и неопределенные индексы, на самом деле помогают сделать ваш код чище и безопаснее. Я могу вам сказать, что несколько лет назад E_NOTICEвключение было вынуждено объявить мои переменные. Это значительно облегчило изучение языка C, если не объявлять переменные, это намного больше неприятностей.

Что я могу сделать об этом?

  1. Выключите E_NOTICE, скопировав «Значение по умолчанию» E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDи заменив его тем, что в данный момент не прокомментировано после входа в систему error_reporting =. Перезапустите Apache или PHP, если используете CGI или FPM. Убедитесь, что вы редактируете «правильный» php.ini. Правильным будет Apache, если вы используете PHP с Apache, fpm или php-fpm, если используете PHP-FPM, cgi, если используете PHP-CGI и т. Д. Это не рекомендуемый метод, но если у вас есть устаревший код, который собирается быть чрезвычайно трудным для редактирования, тогда это может быть вашим лучшим выбором.

  2. Отключите E_NOTICEна уровне файла или папки. Это может быть предпочтительнее, если у вас есть какой-то устаревший код, но в противном случае вы хотите сделать все «правильно». Чтобы сделать это, вы должны проконсультироваться с Apache2, Nginx или любым другим вашим сервером. В Apache вы бы использовали php_valueвнутри <Directory>.

  3. Перепишите свой код, чтобы он стал чище. Если вам нужно сделать это при переходе в производственную среду или вы не хотите, чтобы кто-то видел ваши ошибки, убедитесь, что вы отключили любое отображение ошибок и только регистрируете свои ошибки (см. display_errorsИ log_errorsв php.ini, и в настройках вашего сервера). ,

Чтобы расширить вариант 3: это идеал. Если вы можете пойти по этому пути, вы должны. Если вы изначально не идете по этому пути, рассмотрите возможность его перемещения в конечном итоге, протестировав свой код в среде разработки. Пока вы в этом, избавьтесь ~E_STRICTи ~E_DEPRECATEDпосмотрите, что может пойти не так в будущем. Вы увидите много незнакомых ошибок, но это позволит вам избежать неприятных проблем, когда вам потребуется обновить PHP в будущем.

Что означают ошибки?

Undefined variable: my_variable_name- Это происходит, когда переменная не была определена перед использованием. Когда скрипт PHP выполняется, он просто принимает нулевое значение. Однако в каком сценарии вам нужно проверить переменную, прежде чем она будет определена? В конечном счете, это аргумент в пользу «небрежного кода». Как разработчик, я могу сказать вам, что мне нравится, когда я вижу проект с открытым исходным кодом, где переменные определены настолько высоко, насколько это возможно. Это облегчает определение переменных, которые появятся в будущем, и облегчает чтение / изучение кода.

function foo()
{
    $my_variable_name = '';

    //....

    if ($my_variable_name) {
        // perform some logic
    }
}

Undefined index: my_index- Это происходит, когда вы пытаетесь получить доступ к значению в массиве, а оно не существует. Чтобы предотвратить эту ошибку, выполните условную проверку.

// verbose way - generally better
if (isset($my_array['my_index'])) {
    echo "My index value is: " . $my_array['my_index'];
}

// non-verbose ternary example - I use this sometimes for small rules.
$my_index_val = isset($my_array['my_index'])?$my_array['my_index']:'(undefined)';
echo "My index value is: " . $my_index_val;   

Другой вариант - объявить пустой массив в верхней части вашей функции. Это не всегда возможно.

$my_array = array(
    'my_index' => ''
);

//...

$my_array['my_index'] = 'new string';

(дополнительный совет)

  • Когда я сталкивался с этими и другими проблемами, я использовал IDE NetBeans (бесплатно), и он дал мне множество предупреждений и уведомлений. Некоторые из них предлагают очень полезные советы. Это не является обязательным требованием, и я больше не использую IDE, за исключением крупных проектов. Я больше vimчеловек в эти дни :).
smcjones
источник
6

неопределенный индекс означает в массиве, который вы запросили, например, недоступный индекс массива

<?php 

$newArray[] = {1,2,3,4,5};
print_r($newArray[5]);

?>

неопределенная переменная означает, что вы использовали полностью несуществующую переменную или которая не определена или инициализирована этим именем, например

<?php print_r($myvar); ?>

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

php> echo array_key_exists(1, $myarray);
Sintayehu Abaynhe
источник
4

Относительно этой части вопроса:

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

Определенных ответов нет, но вот некоторые возможные объяснения того, почему настройки могут «внезапно» измениться:

  1. Вы обновили PHP до более новой версии, которая может иметь другие значения по умолчанию для error_reporting, display_errors или других соответствующих настроек.

  2. Вы удалили или ввели некоторый код (возможно, в зависимости), который устанавливает соответствующие параметры во время выполнения, используя ini_set()или error_reporting()(ищите их в коде)

  3. Вы изменили конфигурацию веб-сервера (при условии, что здесь используется apache): .htaccessфайлы и конфигурации vhost также могут управлять настройками php.

  4. Обычно уведомления не отображаются / не отображаются (см. Руководство по PHP ), поэтому возможно, что при настройке сервера файл php.ini не мог быть загружен по какой-то причине (права доступа к файлам ??), и вы были по умолчанию , Позднее «ошибка» была устранена (случайно), и теперь она МОЖЕТ загрузить правильный файл php.ini с установленным значением error_reporting для отображения уведомлений.

Воутер де Винтер
источник
3

При работе с классами вы должны убедиться, что вы ссылаетесь на переменные-члены, используя $this:

class Person
{
    protected $firstName;
    protected $lastName;

    public function setFullName($first, $last)
    {
        // Correct
        $this->firstName = $first;

        // Incorrect
        $lastName = $last;

        // Incorrect
        $this->$lastName = $last;
    }
}
Джон Конде
источник
3

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

То есть:

$query = "SELECT col1 FROM table WHERE col_x = ?";

Затем пытаемся получить доступ к большему количеству столбцов / строк внутри цикла.

То есть:

print_r($row['col1']);
print_r($row['col2']); // undefined index thrown

или в whileцикле:

while( $row = fetching_function($query) ) {

    echo $row['col1'];
    echo "<br>";
    echo $row['col2']; // undefined index thrown
    echo "<br>";
    echo $row['col3']; // undefined index thrown

}

Следует также отметить, что в * NIX OS и Mac OS X все зависит от регистра.

Консультируйтесь со следующими вопросами и ответами на стеке:

оборота Фред -ii-
источник
3

Использование троичного проста, читабельна и чиста:

до PHP 7
Назначьте переменную значению другой переменной, если она установлена, иначе назначьте null(или любое другое значение по умолчанию, которое вам нужно):

$newVariable = isset($thePotentialData) ? $thePotentialData : null;

PHP 7+
То же самое, за исключением использования оператора объединения нулей . Больше нет необходимости вызывать, isset()поскольку это встроено, и нет необходимости предоставлять переменную для возврата, поскольку предполагается, что она возвращает значение проверяемой переменной:

$newVariable = $thePotentialData ?? null;

Оба остановят Уведомления от вопроса OP, и оба являются точным эквивалентом:

if (isset($thePotentialData)) {
    $newVariable = $thePotentialData;
} else {
    $newVariable = null;
}

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

Echo:

echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';

Функция:

$foreName = getForeName(isset($userId) ? $userId : null);

function getForeName($userId)
{
    if ($userId === null) {
        // Etc
    }
}

Вышеприведенное будет работать точно так же с массивами, включая сеансы и т. Д., Заменив проверяемую переменную, например:
$_SESSION['checkMe']
или сколько угодно глубоких уровней, например:
$clients['personal']['address']['postcode']


 

Подавление:

Можно подавить уведомления PHP с помощью @или уменьшить уровень сообщений об ошибках, но это не решает проблему , а просто останавливает сообщение в журнале ошибок. Это означает, что ваш код все еще пытался использовать переменную, которая не была установлена, что может означать или не означать, что что-то не работает должным образом - в зависимости от того, насколько важным является отсутствующее значение.

Вы действительно должны проверять эту проблему и обрабатывать ее соответствующим образом, либо отправляя другое сообщение, либо даже просто возвращая нулевое значение для всего остального, чтобы определить точное состояние.

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

Джеймс
источник
1

Одна распространенная причина того, что переменная не существует после отправки HTML- формы, заключается в том, что элемент формы не содержится в <form>теге:

Пример: элемент не содержится в <form>

<form action="example.php" method="post">
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>

<select name="choice">
    <option value="choice1">choice 1</option>
    <option value="choice2">choice 2</option>
    <option value="choice3">choice 3</option>
    <option value="choice4">choice 4</option>
</select>

Пример: элемент теперь содержится в <form>

<form action="example.php" method="post">
    <select name="choice">
        <option value="choice1">choice 1</option>
        <option value="choice2">choice 2</option>
        <option value="choice3">choice 3</option>
        <option value="choice4">choice 4</option>
    </select>
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>
Джон Конде
источник
0

Вероятно, вы использовали старую версию PHP до и теперь обновили PHP, поэтому он работал без каких-либо ошибок до сих пор от лет. до PHP4 не было никакой ошибки, если вы используете переменную без ее определения, но начиная с PHP5 она выдает ошибки для кодов, подобных упомянутым в вопросе.

phvish
источник
0

При работе с файлами требуются правильный enctype и метод POST, который вызовет неопределенное уведомление об индексе, если оба из них не включены в форму.

В руководстве изложен следующий основной синтаксис:

HTML

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

PHP

<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);

print "</pre>";

?>

Ссылка:

Funk Forty Niner
источник
0

Я задал вопрос по этому поводу, и меня отправили на этот пост с сообщением:

На этот вопрос уже есть ответ здесь:

«Примечание: неопределенная переменная», «Примечание: неопределенный индекс» и «Примечание: неопределенное смещение» с использованием PHP

Я делюсь своим вопросом и решением здесь:

Это ошибка:

введите описание изображения здесь

Строка 154 является проблемой. Вот что я имею в строке 154:

153    foreach($cities as $key => $city){
154        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

Я думаю, что проблема в том, что я пишу, если условия для переменной $city, которая является не ключом, а значением в $key => $city. Во-первых, не могли бы вы подтвердить, является ли это причиной предупреждения? Во-вторых, если это проблема, почему я не могу написать условие, основанное на значении? Это должно быть с ключом, что мне нужно написать условие?

ОБНОВЛЕНИЕ 1: Проблема в том, что при выполнении $citiesCounterArray[$key]иногда $keyсоответствует ключу, который не существует в $citiesCounterArrayмассиве, но это не всегда так, основываясь на данных моего цикла. Что мне нужно, это установить условие, чтобы, если $keyсуществует в массиве, затем запустить код, в противном случае пропустите его.

ОБНОВЛЕНИЕ 2: Вот как я это исправил, используя array_key_exists():

foreach($cities as $key => $city){
    if(array_key_exists($key, $citiesCounterArray)){
        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){
Хайме Монтойя
источник
0

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

Лучший способ справиться с этим - установить отчеты об ошибках во время разработки.

Чтобы настроить отчеты об ошибках:

ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');
error_reporting(E_ALL);

На производственных серверах отчеты об ошибках отключены, поэтому мы не получаем эти ошибки.

Однако на сервере разработки мы можем установить отчеты об ошибках.

Чтобы избавиться от этой ошибки, мы видим следующий пример:

if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

Мы можем инициализировать переменные, NULLпрежде чем присваивать их значения или использовать их.

Итак, мы можем изменить код как:

$test = NULL;
if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

Это не будет нарушать логику программы и не будет создавать Уведомление, даже если $testоно не имеет значения.

Так что, в принципе, всегда лучше устанавливать ON для создания отчетов об ошибках.

И исправить все ошибки.

На производстве отчет об ошибках должен быть отключен.

ученик
источник
-1

Эти уведомления вызваны тем, что у вас нет используемой переменной, definedа my_indexключ отсутствует в $my_arrayпеременной.

Эти уведомления были вызваны каждый раз, потому что ваш code не правы, но, вероятно, вы не сообщали о них.

Решить ошибки:

$my_variable_name = "Variable name"; // defining variable
echo "My variable value is: " . $my_variable_name;

if(isset($my_array["my_index"])){
    echo "My index value is: " . $my_array["my_index"]; // check if my_index is set 
}

Еще один способ получить это:

ini_set("error_reporting", false)
Андрей Тодорут
источник
-2

В PHP вам нужно fist, чтобы определить переменную, после чего вы можете использовать ее.
Мы можем проверить, что переменная определена или не очень эффективно!

//If you only want to check variable has value and value has true and false value.
//But variable must be defined first.

if($my_variable_name){

}

//If you want to check variable is define or undefine
//Isset() does not check that variable has true or false value
//But it check null value of variable
if(isset($my_variable_name)){

}

Простое объяснение

//It will work with :- true,false,NULL
$defineVarialbe = false;
if($defineVarialbe){
    echo "true";
}else{
    echo "false";
}

//It will check variable is define or not and variable has null value.
if(isset($unDefineVarialbe)){
    echo "true";
}else{
    echo "false";
}
Маниш Госвами
источник