"Примітка: Не визначена змінна", "Повідомлення: Не визначений індекс" та "Повідомлення: Не визначений зміщення" за допомогою PHP


1173

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

Який сенс цих повідомлень про помилки?

Чому вони з'являються раптом? Я використовував цей сценарій протягом багатьох років, і ніколи у мене не було проблем.

Як їх виправити?


Це загальне довідкове запитання, до якого люди можуть посилатися як на дублікат, замість того, щоб пояснювати проблему знову і знову. Я вважаю, що це необхідно, тому що більшість реальних відповідей на це питання є дуже конкретними.

Мета Мета:



3
змінна, можливо, не була ініціалізована. Ви ініціалізуєте змінну з публікації чи отримуєте чи будь-який масив? У такому випадку у вас може бути поле у ​​цьому масиві. Це ваш доступ.
Аніш Сільвал

3
@Pekka 웃 - я помітив редагування, додавши "та" Примітка: Не визначене зміщення "" - Чи не було б більше сенсу, використовуючи "PHP:" Не визначена змінна "," Не визначений індекс "," Не визначене зміщення "повідомлення" (навіть взяти . поза PHP, так як воно позначено як «PHP» Плюс до всього , URL отримує обрізається and-notice-undef, просто пропозиція , так що URL не отримує відрізаний Може бути , навіть видалення (занадто багато) котирування Або ..PHP: “Undefined variable/index/offset” notices
Funk Сорок Нінер

2
@Fred Я думаю, що аргумент може бути зроблений для обох варіантів. Є ймовірність, що новачки ввійдуть у весь рядок, включаючи "Повідомлення:" у їх пошуковий запит, який, я впевнений, є основним генератором трафіку для цього питання. Якщо повідомлення там у повному обсязі, це, ймовірно, покращить видимість у пошукових системах
Pekka

2
@Pekka 웃 Я розумію. Я це сказав лише тому, що раніше URL-адресу не відрізали, а зараз це роблять and-notice-undef. Це було лише (декілька) пропозицій. Він просто повторює себе і буттям Notice: Undefined.
Funk Forty Niner

Відповіді:


1066

Примітка: Не визначена змінна

З величезної мудрості посібника з PHP :

Посилатися на значення за замовчуванням неініціалізованої змінної є проблематичним у випадку включення одного файлу в інший, який використовує те саме ім’я змінної. Це також є серйозним ризиком для безпеки із увімкненим register_globals . Помилка рівня E_NOTICE видається у випадку роботи з неініціалізованими змінними, однак не у разі додавання елементів до неініціалізованого масиву. Конструкція мови isset () може використовуватися для виявлення, якщо змінна вже ініціалізована. Додатково і більш ідеальним є рішення порожнього (), оскільки воно не генерує попередження або повідомлення про помилку, якщо змінна не ініціалізується.

З документації PHP :

Якщо змінна не існує, попередження не створюється. Це означає, що порожній () по суті є лаконічним еквівалентом ! 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 змінні є суперглобальними і мають великі регістри .

Пов'язані:


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 способи, тому ви ще не придушили жодних помилок.
Aycan Yaşıt

141

Спробуйте це

Q1: це повідомлення означає, що $ varname не визначено в поточному обсязі сценарію.

Q2: Використання умов isset (), порожніх () перед використанням будь-якої підозрілої змінної працює добре.

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

Примітка про сеанси:


Якщо ви використовуєте 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 / ... .
Гаджус

@GajusKuizinas Запропоновано кілька змін із 2009 року, зокрема php.net/ChangeLog-5.php#5.4.0 суттєво змінює результат (див. "Оператор Zend, продуктивність" та "(тиша)").
Маріо

Дякую @mario, цікаво. Тепер, якщо хтось виявився достатньо хорошим для порівняння двох ... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs Відповідно до цього тесту, схоже, однакові (зауважте, що масштаб змінюється).
Гаджус

47

Взагалі через "погане програмування" та можливість помилок зараз чи пізніше.

  1. Якщо це помилка, спочатку зробіть належне призначення змінній: $ varname = 0;
  2. Якщо це дійсно визначено лише іноді, протестуйте його if (isset($varname))перед тим, як використовувати його
  3. Якщо це тому, що ви написали це неправильно, просто виправте це
  4. Можливо, навіть повернути попередження у ваших PHP-налаштуваннях

5
Не вимикайте попередження. На строгіших мовах вони часто означають, що "може бути помилка, краще перевірити цей рядок двічі" - на мові, вседозволеній, як PHP, вони часто означають, що "цей код лайно і прозаїчно пронизаний помилками; я спробую зробити якесь відчуття цього, але вам краще виправити це якомога швидше ".

5
Хоча я погоджуюся з першими трьома пунктами, №4 просто неправильно. Якщо приховати проблему, вона не зникне, а це може навіть спричинити більше проблем у дорозі.
Валентин Флаксель

1
@Freek абсолютно правда, але в деяких сценаріях (куплений сценарій, нульові технічні знання, потрібні для запуску до завтра ...) це рішення з клейкою стрічкою - дійсно погано, що завжди потрібно наголошувати, але варіант
Pekka

Стрічка-стрічка хороша ... іноді. Історичні попередження були включені у стандартних PHP-налаштуваннях, але налаштування знешкодження стали більш суворими. Шкода, що багато хто повертається до старих налаштувань, щоб не дратувати клієнтів.
Ерік

41

Це означає, що ви тестуєте, оцінюєте чи друкуєте змінну, якій ви ще нічого не призначили. Це означає, що у вас або є помилка друку, або потрібно перевірити, чи змінна була ініціалізована спочатку. Перевірте свої логічні шляхи, він може бути встановлений в одному, а не в іншому.


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 ['ім'я']:

<?=ifexistsidx($_REQUEST,'name')?>

2
Ваша функція ifexists () не працює для мене в PHP 5.3. Змінні виклику не доступні в локальній області функції (див. Область змінної області ), якщо вони не є суперглобалами або ви не змішаєтесь з $ GLOBALS , тому $foo = "BABAR"; ifexists('foo');взагалі повернеться в нуль. (
Курсиви

тепер ви отримаєте "привіт від" ... в чому сенс? просто перевірте значення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');

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;

25

У відповідь на "" Чому вони з'являються раптом? Я використовував цей сценарій роками і ніколи не мав жодних проблем ".

Для більшості сайтів дуже часто працювати в режимі "за замовчуванням" повідомлення про помилки "Показати всі помилки, але не" повідомлення "та" застарілі "". Це буде встановлено у php.ini та стосуватиметься всіх сайтів на сервері. Це означає, що ті "повідомлення", які використовуються в прикладах, будуть придушені (приховані), а інші помилки, які вважаються більш критичними, будуть показані / записані.

Інше важливе значення - помилки, які можна приховати (тобто display_errorsвстановити на "вимкнено" або "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_errorsphp у .htconf (або vhosts тощо) не змінилися
  • Директиви перевірки error_reportingта display_errorsphp в .htaccess не змінилися
  • Якщо у вас є директива в .htaccess, перевірте, чи вони все ще дозволені у файлі .htconf
  • Нарешті перевірте свій код; можливо, непов'язана бібліотека; щоб побачити , якщо error_reportingі display_errorsдирективи PHP були встановлені там.


16

Раніше я проклинав цю помилку, але це може бути корисно нагадати вам уникнути введення користувачем даних.

Наприклад, якщо ви думаєте, що це розумно, скорочуйте код:

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

...Подумати ще раз! Кращим рішенням є:

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

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


15

У 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"] : '');

PHP керівництво PHP 7.0


Це також добре працює, якщо заяви. 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;
}

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ввімкнено можливість змусити мене оголосити свої змінні. Це полегшило засвоєння С, не декларували змінні, що набагато більше неприємності.

ЩО Я МОЖУ РОБИТИ ПРО НАС?

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

(додаткова порада)

  • Коли я стикався з цими та іншими проблемами, я використовував NetBeans IDE (безкоштовно), і це дало мені безліч попереджень та повідомлень. Деякі з них пропонують дуже корисні поради. Це не є вимогою, і я вже не використовую IDE, крім великих проектів. Я більше vimлюдина в ці дні :).

6

невизначений індекс означає в масиві, який ви запитували, наприклад, для недоступного індексу масиву, наприклад

<?php 

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

?>

невизначена змінна означає, що ви використовували повністю не існуючу змінну або яка не визначена або ініціалізована цим іменем, наприклад

<?php print_r($myvar); ?>

невизначений зсув означає в масиві, який ви запитували про неіснуючий ключ. І рішенням цього є перевірка перед використанням

php> echo array_key_exists(1, $myarray);

4

Щодо цієї частини питання:

Чому вони з'являються раптом? Я використовував цей сценарій протягом багатьох років, і ніколи у мене не було проблем.

Немає однозначних відповідей, але ось кілька можливих пояснень того, чому налаштування можуть "раптово" змінитися:

  1. Ви оновили PHP до нової версії, яка може мати інші параметри за замовчуванням для повідомлення про помилки, повідомлення про помилки або інші відповідні налаштування.

  2. Ви видалили або ввели якийсь код (можливо, в залежності), який встановлює відповідні налаштування під час виконання, використовуючи ini_set()або error_reporting()(шукайте їх у коді)

  3. Ви змінили конфігурацію веб-сервера (якщо припустити апаш тут): .htaccessфайли та конфігурації vhost можуть також маніпулювати налаштуваннями php.

  4. Зазвичай повідомлення не відображаються / не надсилаються (див. Посібник із PHP ), тому можливо, що під час налаштування сервера файл php.ini чомусь не вдалося завантажити (права доступу до файлів ??), і ви були за налаштуваннями за замовчуванням . Згодом "помилка" була вирішена (випадково), і тепер вона МОЖЕ завантажувати правильний файл php.ini з набором помилок_репортажу для показу повідомлень.


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 речі залежать від регістру.

Проконсультуйтеся із запитаннями, що складаються в наступному:


3

Використовувати потрійний простий, читабельний і чистий:

Pre PHP 7
Призначте змінну значенню іншої змінної, якщо вона встановлена, інакше призначтеnull(або будь-якезначення за замовчуванням, яке вам потрібно):

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

PHP 7+
Те саме, за винятком використання Null Coalescing Operator . Більше не потрібно викликати, isset()оскільки це вбудовано, і не потрібно надавати змінній для повернення, оскільки передбачається повернути значення змінної, що перевіряється:

$newVariable = $thePotentialData ?? null;

Обидва зупинять Повідомлення від питання щодо ОП, і обидва є точним еквівалентом:

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

 
Якщо вам не потрібно встановлювати нову змінну, ви можете безпосередньо використовувати повернене значення термінала, наприклад, з 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, вона видає помилки для кодів, подібних до питання.


0

При роботі з файлами необхідний належний енктипед та метод 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>";

?>

Довідка:


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 вам потрібен кулак, щоб визначити змінну, після чого ви можете використовувати її.
Ми можемо перевірити, чи вказана змінна чи не дуже ефективний спосіб !.

//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";
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.