1318

PHP スクリプトを実行していますが、次のようなエラーが引き続き発生します。

注意: 未定義の変数: C:\wamp\www\mypath\index.php の 10 行目の my_variable_name

注意: 11 行目の未定義のインデックス: my_index C:\wamp\www\mypath\index.php

警告: C:\wamp\www\mypath\index.php の 11 行目の未定義の配列キー "my_index"

10 行目と 11 行目は次のようになります。

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

これらのエラー メッセージの意味は何ですか?

なぜ彼らは突然現れたのですか?私はこのスクリプトを何年も使用していましたが、問題が発生したことはありません。

どうすれば修正できますか?


これは、問題を何度も説明する代わりに、人々が重複してリンクするための一般的な参照の質問です。この問題に関するほとんどの現実世界の回答は非常に具体的であるため、これが必要だと思います。

関連するメタ ディスカッション:

4

29 に答える 29

1178

Notice / Warning: Undefined variable

From the vast wisdom of the PHP Manual:

Relying on the default value of an uninitialized variable is problematic in the case of including one file into another which uses the same variable name. It is also a major security risk with register_globals turned on. E_NOTICE level error is issued in case of working with uninitialized variables, however not in the case of appending elements to the uninitialized array. isset() language construct can be used to detect if a variable has been already initialized. Additionally and more ideal is the solution of empty() since it does not generate a warning or error message if the variable is not initialized.

From PHP documentation:

No warning is generated if the variable does not exist. That means empty() is essentially the concise equivalent to !isset($var) || $var == false.

This means that you could use only empty() to determine if the variable is set, and in addition it checks the variable against the following, 0, 0.0, "", "0", null, false or [].

Example:

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

Test the above snippet in the 3v4l.org online PHP editor

Although PHP does not require a variable declaration, it does recommend it in order to avoid some security vulnerabilities or bugs where one would forget to give a value to a variable that will be used later in the script. What PHP does in the case of undeclared variables is issue a very low level error, E_NOTICE, one that is not even reported by default, but the Manual advises to allow during development.

Ways to deal with the issue:

  1. Recommended: Declare your variables, for example when you try to append a string to an undefined variable. Or use isset() / !empty() to check if they are declared before referencing them, as in:

    //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'] : '';
    

This has become much cleaner as of PHP 7.0, now you can use the null coalesce operator:

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
  1. Set a custom error handler for E_NOTICE and redirect the messages away from the standard output (maybe to a log file):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
    
  2. Disable E_NOTICE from reporting. A quick way to exclude just E_NOTICE is:

    error_reporting( error_reporting() & ~E_NOTICE )
    
  3. Suppress the error with the @ operator.

Note: It's strongly recommended to implement just point 1.

Notice: Undefined index / Undefined offset / Warning: Undefined array key

This notice/warning appears when you (or PHP) try to access an undefined index of an array.

Ways to deal with the issue:

  1. Check if the index exists before you access it. For this you can use isset() or 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. The language construct list() may generate this when it attempts to access an array index that does not exist:

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

Two variables are used to access two array elements, however there is only one array element, index 0, so this will generate:

Notice: Undefined offset: 1

#$_POST / $_GET / $_SESSION variable

The notices above appear often when working with $_POST, $_GET or $_SESSION. For $_POST and $_GET you just have to check if the index exists or not before you use them. For $_SESSION you have to make sure you have the session started with session_start() and that the index also exists.

Also note that all 3 variables are superglobals and are uppercase.

Related:

于 2010-11-23T21:36:14.763 に答える
162

これらを試してください

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

セッションに関する注意:

于 2010-11-23T21:31:08.227 に答える
75

エラー表示@演算子

望ましくない冗長な通知については、専用の@演算子を使用して »定義 « 未定義の変数/インデックス メッセージを非表示にすることができます。

$var = @($_GET["optional_param"]);
  • これは通常、推奨されません。新規参入者はそれを使いすぎる傾向があります。
  • 関数パラメータやループなど、アプリケーション ロジックの奥深くにあるコード (宣言されていない変数を無視してはなりません) には非常に不適切です。
  • isset?:ただし、??スーパーサプレッションには利点が1 つあります。通知は引き続きログに記録されます。そして、次のようにし@て、隠された通知を復活させることができます: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 も何らかのリライトを行う可能性があります。提供された raw$_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=or属性ではtitle=不十分です。
    • method=POSTフォームに入力する必要があります$_POST
    • a method=GET(またはそれを省略する)と$_GET変数が生成されます。
    • フォームが $_GET と$_POSTaction=script.php?get=paramの残りのフィールドを介して提供することも可能です。method=POST
    • 最新の PHP 構成 (≥ 5.6) では、GET と POST のパラメーターをマッシュアップして、再び使用することが可能になりました (ファッショナブルではありません)。$_REQUEST['vars']
  • mod_rewrite を使用している場合は、両方をチェックし、存在しないパラメータを検出access.logできるようにする必要があります。RewriteLog

$_FILES

$_COOKIE

  • 配列はの$_COOKIE直後に入力されることはなくsetcookie()、フォローアップ HTTP リクエストでのみ入力されます。
  • さらに、有効期限が切れ、サブドメインまたは個々のパスに制約される可能性があり、ユーザーとブラウザーはそれらを拒否または削除できます。
于 2010-11-23T21:40:48.250 に答える
53

一般に、「悪いプログラミング」が原因であり、現在または後で間違いが発生する可能性があります。

  1. 間違っている場合は、最初に変数に適切な代入を行います: $varname=0;
  2. 本当に時々しか定義されない場合は、 if (isset($varname))使用する前にテストしてください:
  3. スペルが間違っているのであれば、それを修正してください
  4. PHP設定の警告を消すことさえあるかもしれません
于 2010-11-23T21:31:48.923 に答える
47

It means you are testing, evaluating, or printing a variable that you have not yet assigned anything to. It means you either have a typo, or you need to check that the variable was initialized to something first. Check your logic paths, it may be set in one path but not in another.

于 2010-11-23T21:35:20.473 に答える
38

役立つので通知を無効にしたくはありませんでしたが、入力しすぎないようにしたかったのです。

私の解決策はこの機能でした:

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

したがって、$name を参照し、存在する場合はエコーする場合は、単純に次のように記述します。

<?= ifexists('name') ?>

配列要素の場合:

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

$_REQUEST['name'] を参照したい場合のページ:

<?= ifexistsidx($_REQUEST, 'name') ?>
于 2011-12-30T14:14:59.830 に答える
30

これは、変数「$user_location」が定義されていないためです。'$user_location' 変数を宣言している内部でif ループを使用している場合は、 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;
于 2012-12-29T11:46:28.537 に答える
29

「なぜ突然現れたのですか?」 への返信 このスクリプトを何年も使用していましたが、問題が発生したことは一度もありません。」

ほとんどのサイトが、「すべてのエラーを表示しますが、「通知」および「非推奨」は表示しない」という「デフォルト」のエラー報告の下で動作することは非常に一般的です。これは php.ini で設定され、サーバー上のすべてのサイトに適用されます。これは、例で使用されている「通知」が抑制 (非表示) され、より重大と見なされる他のエラーが表示/記録されることを意味します。

もう 1 つの重要な設定は、エラーを非表示にできることです (つまりdisplay_errors、「オフ」または「syslog」に設定)。

この場合、error_reportingが通知も表示するように変更された (例のように) か、設定がdisplay_errors画面に表示されるように変更された (通知を抑制/ログに記録するのではなく) ようになりました。

なぜ彼らは変わったのですか?

明白で最も単純な答えは、誰かが php.ini でこれらの設定のいずれかを調整したか、アップグレードされたバージョンの PHP が以前とは異なる php.ini を使用しているということです。それが最初に見る場所です。

ただし、これらの設定をオーバーライドすることもできます

  • .htconf (仮想ホストとサブ構成を含む Web サーバー構成)*
  • .htaccess
  • PHPコード自体で

また、これらのいずれも変更されている可能性があります。

また、Web サーバーの構成で .htaccess ディレクティブを有効/無効にできるという複雑な問題もあります。そのため、.htaccess に突然動作を開始/停止するディレクティブがある場合は、それを確認する必要があります。

(.htconf / .htaccess は、Apache として実行していることを前提としています。コマンド ラインを実行している場合、これは適用されません。IIS または他の Web サーバーを実行している場合は、それに応じてこれらの構成を確認する必要があります)

概要

  • php.ini の php ディレクティブが変更されていないか、以前とは異なる php.ini を使用していないことを確認error_reportingしてください。display_errors
  • .htconf (または vhosts など) のCheckerror_reportingおよびphp ディレクティブは変更されていませんdisplay_errors
  • .htaccess のCheckerror_reportingおよびdisplay_errorsphp ディレクティブは変更されていません
  • .htaccess にディレクティブがある場合は、それらがまだ .htconf ファイルで許可されているかどうかを確認してください
  • 最後にコードを確認してください。おそらく無関係のライブラリ。error_reportingおよびdisplay_errorsphp ディレクティブがそこに設定されているかどうかを確認します。
于 2016-11-23T01:44:03.197 に答える
25

簡単な修正は、コードの先頭で変数を null に割り当てることです。

$user_location = null;
于 2014-05-12T19:02:26.150 に答える
22

なぜこうなった?

時間の経過とともに、PHP はよりセキュリティ重視の言語になりました。デフォルトでオフになっていた設定が、デフォルトでオンになりました。これの完璧な例は、 PHP 5.4.0E_STRICT以降でデフォルトで有効になった です。

さらに、PHP のドキュメントによると、デフォルトでE_NOTICEは、ファイルphp.iniで無効になっています。PHP のドキュメントでは、デバッグ目的で有効にすることを推奨しています。しかし、Ubuntu リポジトリと BitNami の Windows スタックから PHP をダウンロードすると、別のことがわかります。

; 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 の学習が大幅に容易になりました。C では、変数を宣言しないことは非常に厄介です。

私はそれについて何ができますか?

  1. E_NOTICE「デフォルト値」E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDをコピーし、等号の後に現在コメント解除されているものに置き換えることでオフにしerror_reporting =ます。CGI または FPM を使用している場合は、Apache または PHP を再起動します。「正しい」php.iniファイルを編集していることを確認してください。PHP を Apache で実行している場合は Apache、PHP-FPM を実行している場合は fpm または php-fpm、PHP-CGI を実行している場合は cgi などです。これは推奨される方法ではありませんが、レガシー コードを使用する場合は編集が非常に難しい場合は、それが最善の策かもしれません。

  2. E_NOTICEファイルまたはフォルダー レベルでオフにします。これは、レガシー コードがあり、それ以外の場合は「正しい」方法で処理したい場合に適している場合があります。これを行うには、Apache 2、Nginx、または選択したサーバーに相談する必要があります。Apache では、php_value内で使用します<Directory>

  3. コードを書き直して、よりクリーンにします。本番環境への移行中にこれを行う必要がある場合、またはエラーを誰かに見られたくない場合は、エラーの表示を無効にし、エラーのみを記録していることを確認してください ( php.ini およびサーバー設定の および をdisplay_errors参照) 。 log_errors.

オプション 3 を拡張するには: これが理想です。この道を行くことができるなら、そうすべきです。最初はこのルートに進まない場合は、開発環境でコードをテストして、最終的にこのルートに移行することを検討してください。あなたがそれに取り組んでいる間に、それを取り除き~E_STRICT~E_DEPRECATED将来何がうまくいかないかを見てください. なじみのないエラーがたくさん表示されることになりますが、将来 PHP をアップグレードする必要があるときに不快な問題が発生するのを防ぐことができます。

エラーは何を意味しますか?

Undefined variable: my_variable_name・ 変数を定義せずに使用した場合に発生します。PHP スクリプトが実行されると、内部的に単に null 値を想定します。ただし、変数を定義する前にチェックする必要があるのはどのシナリオですか? 結局のところ、これは「ずさんなコード」の議論です。開発者として、変数が定義可能な限りスコープ内で定義されているオープンソース プロジェクトを見ると、私はそれが好きだと言えます。これにより、将来どの変数がポップアップするかがわかりやすくなり、コードの読み取り/学習が容易になります。

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;

もう 1 つのオプションは、関数の先頭で空の配列を宣言することです。これは常に可能であるとは限りません。

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

//...

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

(追加のヒント)

  • これらの問題やその他の問題に遭遇したとき、NetBeanss IDE (無料) を使用したところ、多くの警告と通知が表示されました。それらのいくつかは、非常に役立つヒントを提供します。これは必須ではなく、大規模なプロジェクト以外では IDE を使用しなくなりました。私はvim最近、より人間的です:)。
于 2016-11-28T23:01:31.667 に答える
19

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

于 2016-12-13T13:34:57.600 に答える
8

質問のこの部分について:

なぜ彼らは突然現れたのですか?私はこのスクリプトを何年も使用していましたが、問題が発生したことはありません。

明確な答えはありませんが、設定が「突然」変更される理由のいくつかの可能な説明を次に示します。

  1. PHP を新しいバージョンにアップグレードしました。このバージョンでは、error_reporting、display_errors、またはその他の関連する設定に他のデフォルトを設定できます。

  2. ini_set()またはを使用して実行時に関連する設定を設定するいくつかのコードを削除または導入しました (おそらく依存関係にありますerror_reporting()) (コード内でこれらを検索します)。

  3. Web サーバーの構成を変更しました (ここでは apache を想定しています):.htaccessファイルと vhost の構成でも php の設定を操作できます。

  4. 通常、通知は表示/報告されません ( PHP のマニュアルを参照)。そのため、サーバーのセットアップ時に、何らかの理由 (ファイルのアクセス許可??) で php.ini ファイルをロードできず、デフォルト設定のままだった可能性があります。 . その後、「バグ」は (偶然に) 解決され、通知を表示するように設定された error_reporting を使用して、正しい php.ini ファイルをロードできるようになりました。

于 2016-11-28T19:31:39.140 に答える
7

三項演算子を使用すると、シンプルで読みやすく、きれいになります。

PHP 7より前

変数が設定されている場合は別の変数の値に割り当て、そうでない場合は割り当てますnull(または必要なデフォルト値):

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

PHP 7+

null 合体演算子を使用する以外は同じです。これは組み込まれているため、呼び出す必要がなくなりました。またisset()、チェックされている変数の値を返すと想定されているため、返す変数を提供する必要もありません。

$newVariable = $thePotentialData ?? null;

どちらもOPの質問からの通知を停止し、どちらも次のものとまったく同じです。

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

新しい変数を設定する必要がない場合は、 with 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 通知を抑制し@たり、エラー レポート レベルを下げたりすることは可能ですが、問題は解決しません。エラーログで報告されないようにするだけです。これは、コードがまだ設定されていない変数を使用しようとしたことを意味します。これは、欠損値がどれほど重要かによって、何かが意図したとおりに機能しないことを意味する場合とそうでない場合があります。

この問題を実際に確認し、適切に処理して、別のメッセージを提供するか、正確な状態を識別するために他のすべてに null 値を返す必要があります。

通知がエラー ログにないことだけを気にする場合は、オプションとしてエラー ログを無視することもできます。

于 2018-07-06T18:56:38.890 に答える
4

未定義のインデックス通知がスローされるもう 1 つの理由は、データベース クエリから列が省略されたことです。

すなわち:

$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 では、大文字と小文字が区別されるということです。

Stack に関する次の Q&A を参照してください。

于 2017-07-24T16:11:08.433 に答える
-1

これらの通知は、使用されている変数がなく、変数definedmy_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)
于 2018-01-25T13:09:56.930 に答える