Я использую скрипт 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"];
В чем смысл этих сообщений об ошибках?
Почему они появляются внезапно? Я использовал этот сценарий в течение многих лет, и у меня никогда не было проблем.
Как мне их исправить?
< час / >
Это общий справочный вопрос , на который люди могут ссылаться как дубликат, вместо того, чтобы объяснять проблему снова и снова. Я чувствую, что это необходимо, потому что большинство реальных ответов по этому вопросу очень специфичны. & Лт; / sub >
Связанное обсуждение мета: < / sub >
- Что можно сделать с повторяющимися вопросами? < / sub >
- Имеют ли «ссылочные вопросы» смысл? < / sub >
Из огромной мудрости Руководства PHP:
Полагаться на значение по умолчанию для неинтилизованной переменной проблематично в случае включения одного файла в другой, который использует то же имя переменной. Это также серьезный риск безопасности с включенным register_globals. Ошибка уровня E_NOTICE выдается в случае работы с ненициализированными переменными, однако не в случае добавления элементов в ненитиализованный массив. isset () языковая конструкция может использоваться для обнаружения, была ли переменная уже инициализирована. Кроме того, более идеальным является решение empty (), поскольку оно не генерирует предупреждение или сообщение об ошибке, если переменная не инициализирована.
Из документации PHP:
Предупреждение не генерируется, если переменная не существует. Это значит empty () по сути является кратким эквивалентом !isset ($ var) || $ var == ложный .
Это означает, что вы можете использовать только empty ()
, чтобы определить, установлена ли переменная, и, кроме того, она проверяет переменную на соответствие следующим, 0
, 0.0
, "",
" 0" ,
null,
falseили
[] `.
Пример:
& Лт;?php
$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 не требует объявления переменных, он рекомендует его, чтобы избежать некоторых уязвимостей безопасности или ошибок, при которых можно забыть придать значение переменной, которая будет использоваться позже в скрипте. В случае незаявленных переменных PHP выдает ошибку очень низкого уровня, E_NOTICE
, о которой даже не сообщается по умолчанию, но в Руководстве рекомендуется разрешить во время разработки.
Способы решения проблемы:
Рекомендовано: Объявите свои переменные, например, когда вы пытаетесь добавить строку к неопределенной переменной. Или используйте isset ()
/ !empty ()
, чтобы проверить, объявлены ли они, прежде чем ссылаться на них, как в:
// Инитиализация переменной
$ value = ""; // Инитиализация стоимости; Примеры
// "" Когда вы хотите добавить материал позже
// 0 Если вы хотите добавить цифры позже
//isset ()
$ value = isset ($ _POST ['value']) ? $ _POST ['значение']: '';
//пустой()
$ value = !пустой ($ _POST ['значение']) ? $ _POST ['значение']: '';
Это стало намного чище с PHP 7.0, теперь вы можете использовать нулевой оператор coalesce:
// Нулевой оператор объединения - нет необходимости явно инициализировать переменную.
$ value = $ _POST ['value'] ?? «;
Установите custom обработчик ошибок для E_NOTICE и перенаправьте сообщения из стандартного вывода (возможно, в файл журнала):
set_error_handler ('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
Отключить E_NOTICE от отчетности. Быстрый способ исключить просто E_NOTICE
это:
error_reporting (error_reporting () & ~ E_NOTICE)
Подавить ошибку с помощью @ operator.
Примечание: Настоятельно рекомендуется реализовать только пункт 1.
Это уведомление появляется, когда вы (или PHP) пытаетесь получить доступ к неопределенному индексу массива.
Способы решения проблемы:
Проверьте, существует ли индекс, прежде чем получить к нему доступ. Для этого вы можете использовать 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']: '';
Языковая конструкция 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 ()
и что индекс также существует.
Также обратите внимание, что все 3 переменные являются суперглобалами и являются прописными.
Связанный:
Попробуй это
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 ();
необходимо размещать во всех файлах с помощью сеансов.
@
операторДля нежелательных и избыточных уведомлений можно использовать выделенный оператор @
- & # 187; скрыть & # 171; неопределенные сообщения переменной / индекса.
$var = @($_GET["optional_param"]);
isset?:
или??
Супрессия однако. Уведомления все еще могут быть зарегистрированы. И можно воскресить @
- скрытые уведомления с помощью: set_error_handler ("var_dump");
if (isset ($ _POST ["shubmit"])
в вашем первоначальном коде.@
или isset
только после проверки функциональности.Исправьте причину в первую очередь. Не уведомления.
@
в основном приемлемо для входных параметров $ _GET
/ $ _POST
, в частности если они необязательны .И поскольку это охватывает большинство таких вопросов, давайте рассмотрим наиболее распространенные причины:
$ _GET
/ $ _POST
/ $ _REQUEST
неопределенный вводПервое, что вы делаете при столкновении с неопределенным индексом / смещением, это проверка опечаток: `$ count = $ _GET ["whatnow?«];»
Во-вторых, если уведомление не имеет очевидной причины, используйте var_dump
или print_r
для проверки все входные массивы для их текущего содержимого:
var_dump ($ _GET) ;
var_dump ($ _POST) ;
//print_r ($ _REQUEST) ;
Оба покажут, был ли ваш скрипт вызван с правильным или каким-либо параметром вообще.
Альтернативно или дополнительно используйте ваши [ browser devtools ( F12 < / kbd >)](https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor #Network_request_details) и проверить вкладку сети для запросов и параметров:
инструменты разработчика браузера / вкладка сети! Параметры POST и ввод GET будут показаны отдельно.
Для параметров $ _GET
вы также можете заглянуть в QUERY_STRING
в
print_r ($ _SERVER) ;
В PHP есть некоторые правила для coalesce нестандартных имен параметров в суперглобалах. Apache также может сделать переписывание.
Вы также можете посмотреть на поставляемые необработанные $ _COOKIES
и другие заголовки HTTP-запросов таким образом.
Более очевидно, посмотрите на адресную строку вашего браузера для параметры GET:
http://example.org/script.php?id = 5 & sort = desc
< / kbd >
Name = value
пары после ?
ознаменование вопроса - это параметры вашего запроса (GET). Таким образом, этот URL может давать только $ _GET ["id"]
и$ _GET ["sort"]
.
Наконец, проверьте свои < form >
и< input >
декларации, если вы ожидаете параметр, но не получаете его.
< input = FOO >
id =
или title =
не достаточно.method = POST
должна заполнять $ _POST
.method = GET
(или оставляя его вне) даст переменные $ _GET
.action = script.php?get = param
через $ _GET и оставшиеся поля method = POST
в $ _POST вместе.$_REQUEST ['vars']
](http://php.net/reserved.variable.re.Если вы используете mod_rewrite, вам следует проверить как access.log
, так и включить RewriteLog
, чтобы выяснить отсутствующие параметры.
$ _FILES
$ _ FILES ["formname"]
.enctype = multipart / form-data
method = POST
в вашей декларации < form >
.$ _COOKIE
$ _COOKIE
никогда не заполняется сразу после setcookie ()
, но только в любом последующем HTTP-запросе.Обычно из-за «плохого программирования» и возможности ошибок сейчас или позже.
if (isset ($ varname))
, перед использованиемЭто означает, что вы тестируете, оцениваете или печатаете переменную, которой вы еще ничего не назначили. Это означает, что у вас либо есть опечатка, либо вам нужно проверить, что переменная была инициализирована чем-то первым. Проверьте свои логические пути, он может быть установлен на одном пути, но не на другом.
Я не хотел отключать уведомление, потому что это полезно, но хотел избежать слишком большого набора текста.
Моим решением была эта функция:
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')?>
Лучший способ получить ввод string - это:
$value = filter_input(INPUT_POST, 'value');
Этот однострочник почти эквивалентен:
if (!isset($_POST['value'])) {
$value = null;
} elseif (is_array($_POST['value'])) {
$value = false;
} else {
$value = $_POST['value'];
}
Если вы абсолютно хотите значение string , просто как:
$value = (string)filter_input(INPUT_POST, 'value');
В ответ на «Почему они появляются внезапно? Я использовал этот сценарий в течение многих лет, и у меня никогда не было проблем.«
Большинство сайтов очень часто работают под сообщением об ошибках «по умолчанию» «Показать все ошибки, но не« уведомления »и« устаревшие »». Это будет установлено в php.ini и применимо ко всем сайтам на сервере. Это означает, что те «уведомления», которые используются в примерах, будут подавлены (скрыты), в то время как другие ошибки, считающиеся более критическими, будут показаны / записаны.
Другая критическая настройка - ошибки могут быть скрыты (т.е. display_errors
установлен в «off» или «syslog»).
В этом случае произойдет то, что либо «error_reporting» был изменен, чтобы также отображать уведомления (в соответствии с примерами) и / или что настройки были изменены на «display_errors» на экране (в отличие от их подавления / регистрации).
Почему они изменились?
Очевидный / простой ответ заключается в том, что кто-то настроил любой из этих настроек в php.ini или обновленную версию PHP, теперь использует другой php.ini, чем раньше. Это первое место, чтобы посмотреть.
Однако также можно переопределить эти настройки в
и любой из них также мог быть изменен.
Также добавлено усложнение, что конфигурация веб-сервера может включать / отключать директивы .htaccess, поэтому, если у вас есть директивы в .htaccess, которые внезапно запускаются / прекращают работать, вам нужно проверить это.
(.htconf / .htaccess предполагают, что вы работаете как apache. Если выполняется командная строка, это не будет применяться; если вы используете IIS или другой веб-сервер, вам нужно будет проверить эти конфигурации соответствующим образом)
Резюме
error_reporting
и display_errors
в php.ini не изменились, или что вы не используете другой php.ini из предыдущего.error_reporting
и display_errors
в .htconf (или vhosts и т. Д.) Не измениласьerror_reporting
и display_errors
в .htaccess не изменилисьerror_reporting
и display_errors
.Это потому, что переменная '$ 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;
быстрое исправление - назначить вашу переменную нулевой в верхней части кода
$user_location = null;
Раньше я проклинал эту ошибку, но может быть полезно напомнить вам об избежании пользовательского ввода.
Например, если вы подумали, что это умный, сокращенный код:
// Echo whatever the hell this is
<?=$_POST['something']?>
Подумай еще раз.. Лучшее решение:!
// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>
(Я использую пользовательскую функцию html ()
, чтобы избежать символов, ваш пробег может отличаться)
В PHP 7.0 теперь можно использовать оператор объединения Null:
echo "My index value is: " . ($my_array["my_index"] ?? '');
Равно:
echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');
На очень простом языке .< br / > Ошибка в том, что вы используете переменную $ user_location
, которая не определена вами ранее и не имеет никакого значения. Поэтому я рекомендую вам указать declare эту переменную до с использованием , Например: < hr / > $ user_location *
Это очень распространенная ошибка, с которой вы можете столкнуться. Так что не беспокойтесь, просто объявите переменную и Enjoy Coding .
Я использую все время собственную полезную функцию 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;
}
почему бы не сделать все просто?
<?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
?>
Со временем 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, поэтому я не подтвердил это в других дистрибутивах.
Однако, чтобы ответить на ваш вопрос, эта ошибка появляется сейчас, когда она не появлялась раньше, потому что:
Вы установили PHP, и новые настройки по умолчанию несколько плохо документированы, но не исключают E_NOTICE
.
Предупреждения E_NOTICE
, такие как неопределенные переменные и неопределенные индексы, действительно помогают сделать ваш код более чистым и безопасным. Я могу вам сказать, что несколько лет назад включение «E_NOTICE» заставило меня объявить свои переменные. Это сделало намного проще изучение C, если не объявлять переменные гораздо больше неприятностей.
Выключите 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 и т. Д. Это не рекомендуемый метод, но если у вас есть устаревший код, который будет чрезвычайно трудно редактировать, то это может быть вашим лучшим выбором.
Выключите E_NOTICE
на уровне файла или папки. Это может быть предпочтительнее, если у вас есть какой-то устаревший код, но вы хотите делать все «правильно» в противном случае. Для этого вам следует обратиться к Apache2, Nginx или к любому другому серверу. В Apache вы должны использовать php_value
внутри < Directory >
.
Перепишите свой код, чтобы быть чище. Если вам нужно сделать это при переходе в производственную среду или не хотите, чтобы кто-то видел ваши ошибки, убедитесь, что вы отключаете любое отображение ошибок и только регистрируете ваши ошибки (см. display_errors
и log_errors
в php.ini и настройках вашего сервера).
Чтобы расширить вариант 3: Это идеал. Если вы можете пойти по этому маршруту, вы должны. Если вы изначально не идете по этому маршруту, подумайте о том, чтобы в конечном итоге переместить этот маршрут, протестировав свой код в среде разработки. Пока вы на этом, избавьтесь от ~ E_STRICT
и ~ E_DEPRECATED
, чтобы увидеть, что может пойти не так в будущем. Вы увидите много незнакомых ошибок, но это остановит вас от неприятных проблем, когда вам нужно обновить PHP в будущем.
Неопределенная переменная: my_variable_name
- это происходит, когда переменная не была определена перед использованием. Когда скрипт PHP выполняется, он внутренне просто принимает нулевое значение. Однако в каком сценарии вам нужно будет проверить переменную, прежде чем она будет определена? В конечном счете, это аргумент для «небрежного кода». Как разработчик, я могу сказать вам, что мне нравится, когда я вижу проект с открытым исходным кодом, где переменные определяются как высоко в их области, насколько они могут быть определены. Это облегчает определение того, какие переменные будут появляться в будущем, и облегчает чтение / изучение кода.
function foo()
{
$my_variable_name = '';
//....
if ($my_variable_name) {
// perform some logic
}
}
Неопределенный индекс: 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';
например, неопределенный индекс означает в массиве, который вы запросили для недоступного индекса массива
<?php
$newArray[] = {1,2,3,4,5};
print_r($newArray[5]);
?>
неопределенная переменная означает, что вы использовали совершенно несуществующую переменную или которая не определена или не инициализирована этим именем, например
<?php print_r($myvar); ?>
неопределенное смещение означает, что в массиве вы запросили несуществующий ключ. И Решение для этого - проверить перед использованием
php> echo array_key_exists(1, $myarray);
Относительно этой части вопроса:
Почему они появляются внезапно? Я использовал этот сценарий в течение многих лет, и у меня никогда не было проблем.
Нет определенных ответов, но вот некоторые возможные объяснения того, почему настройки могут «внезапно» измениться:
Вы обновили PHP до более новой версии, которая может иметь другие значения по умолчанию для error_reporting, display_errors или других соответствующих настроек.
Вы удалили или ввели некоторый код (возможно, в зависимости), который устанавливает соответствующие настройки во время выполнения, используя ini_set ()
или error_reporting ()
(поиск их в коде)
Вы изменили конфигурацию веб-сервера (при условии apache здесь): файлы .htaccess
и конфигурации vhost также могут манипулировать настройками php.
Обычно уведомления не отображаются / не сообщаются (см. Руководство PHP) поэтому возможно, что при настройке сервера файл php.ini не может быть загружен по какой-либо причине (разрешения для файлов)??) и вы были на настройках по умолчанию. Позже, «ошибка» была решена (случайно), и теперь она МОЖЕТ загрузить правильный файл php.ini с помощью параметра error_reporting, установленного для отображения уведомлений.
При работе с классами вам необходимо убедиться, что вы ссылаетесь на переменные участника, используя $ this
:
class Person
{
protected $firstName;
protected $lastName;
public function setFullName($first, $last)
{
// Correct
$this->firstName = $first;
// Incorrect
$lastName = $last;
// Incorrect
$this->$lastName = $last;
}
}
Еще одна причина, по которой будет добавлено неопределенное уведомление об индексе, заключается в том, что столбец был опущен в запросе базы данных.
Т.е.:
$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 все зависит от конкретного случая.
Обратитесь к разделу вопросов и ответов на стек: