使用 PHP 的 “Notice: Undefined variable”, “Notice: Undefined index”, “Warning: Undefined array key” 和 “Notice: Undefined offset”

"Notice: Undefined variable", "Notice: Undefined index", "Warning: Undefined array key", and "Notice: Undefined offset" using PHP

提问人: 提问时间:11/24/2010 最后编辑:32 revs, 22 users 21%Pekka 更新时间:5/29/2023 访问量:2167934

问:

我正在运行PHP脚本,并继续收到以下错误:

注意:未定义的变量:my_variable_name在第 10 行的 C:\wamp\www\mypath\index.php

注意:未定义索引:my_index C:\wamp\www\mypath\index.php第 11 行

警告:第 11 行 C:\wamp\www\mypath\index 中未定义的数组键“my_index”.php

第 10 行和第 11 行如下所示:

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

这些错误消息的含义是什么?

为什么它们会突然出现?我曾经使用这个脚本多年,我从来没有遇到过任何问题。

如何修复它们?


这是一个一般参考问题,人们可以将其作为重复链接,而不必一遍又一遍地解释问题。我觉得这是必要的,因为关于这个问题的大多数现实世界的答案都非常具体。

相关元讨论:

php 数组 变量 警告 undefined-index

评论

15赞 user229044 10/8/2013
引用的可能重复 - 这个错误在PHP中是什么意思?
4赞 Anish Silwal 12/15/2015
变量可能尚未初始化。您是否正在从 post 或 get 或任何数组初始化变量?如果是这种情况,则该数组中可能没有字段。您的访问。
4赞 Funk Forty Niner 1/20/2017
@Pekka웃 - 我注意到编辑添加了“和”注意:未定义的偏移量“” - 使用“PHP: ”未定义的变量“, ”未定义的索引“, ”未定义的偏移量“ 通知”(甚至取出 PHP,因为它被标记为“php”。另外,URL 在 被切断,只是一个建议,这样 URL 就不会被切断。甚至可能删除(太多)引号。或and-notice-undefPHP: “Undefined variable/index/offset” notices
4赞 Pekka 1/20/2017
@Fred我想可以对这两种变体进行论证。新手有机会进入整个行,包括“通知:”进入他们的搜索查询,我敢肯定这是这个问题的主要流量来源。如果消息完整存在,这可能会提高搜索引擎的可见度
3赞 Funk Forty Niner 1/20/2017
@Pekka웃 我明白。我之所以这么说,是因为 URL 以前没有被切断,现在它在 .这只是一个(几个)建议。它只是重复自己也是.and-notice-undefNotice: Undefined

答:

171赞 9 revs, 5 users 62%Ish #1

试试这些

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

关于会话的注意事项:

评论

0赞 ahmd0 10/4/2014
如果从配置文件中使用,请执行E_NOTICEphp.inierror_reporting = (E_ALL & ~E_NOTICE)
1赞 Script47 6/25/2018
这个答案正在 meta 上讨论。
0赞 4/25/2020
从上面的答案来看,我尝试过 isset,array_key_exists但那些都没有用。我尝试了你的答案 .empty(),它有效。谢谢!
0赞 Ganesan J 7/2/2022
非常感谢。我添加了“error_reporting(E_ALL ^ E_NOTICE);”这对我有用。
54赞 2 revs, 2 users 83%Erik #2

通常是因为“糟糕的编程”,以及现在或以后出错的可能性。

  1. 如果是错误的,请先对变量进行适当的赋值:$varname=0;
  2. 如果它真的只是偶尔定义,请在使用它之前测试它:if (isset($varname))
  3. 如果是因为拼写错误,请纠正它
  4. 甚至可能在您的PHP设置中打开警告

评论

7赞 11/24/2010
请不要关闭警告。在更严格的语言中,它们通常意味着“可能存在错误,你最好检查两次这一行”——在像 PHP 这样宽松的语言中,它们通常意味着“这段代码很糟糕,而且可能充满了错误;我会试着弄清楚它,但你最好尽快解决这个问题”。
5赞 Valentin Flachsel 11/24/2010
虽然我同意前三点,但#4 是完全错误的。隐藏问题不会让它消失,它甚至可能导致更多的问题。
2赞 Pekka 11/24/2010
@Freek绝对正确,但在某些情况下(购买了脚本,技术知识为零,需要在明天之前运行......),这是胶带解决方案 - 真的很糟糕,总是需要强调,但是一种选择
48赞 2 revsDGM #3

这意味着您正在测试、评估或打印尚未为其分配任何内容的变量。这意味着您要么有拼写错误,要么需要先检查变量是否已初始化为某些内容。检查您的逻辑路径,它可能设置在一个路径中,但不能设置在另一个路径中。

1214赞 35 revs, 16 users 32%Your Common Sense #4

此错误消息旨在帮助 PHP 程序员在访问不存在的变量(或数组元素)时发现拼写错误或错误。所以一个好的程序员:

  1. 确保每个变量或数组键在使用时都已定义。如果需要在函数内部使用变量,则必须将其作为参数传递给该函数。
  2. 注意此错误并继续修复它,就像处理任何其他错误一样。它可能表示拼写错误,或者某些过程未返回应有的数据。
  3. 只有在极少数情况下,当事情不在程序员的控制之下时,才能添加代码来规避此错误。但这绝不应该是一种盲目的习惯。

通知/警告:未定义的变量

虽然 PHP 不需要变量声明,但它确实推荐它以避免一些安全漏洞或错误,在这些漏洞或错误中,人们会忘记为稍后将在脚本中使用的变量赋值。PHP 在未声明变量的情况下所做的是发出 level 错误。E_WARNING

此警告可帮助程序员发现拼写错误的变量名称或类似类型的错误(例如,在计算结果为 false 的条件中为变量分配了一个值)。此外,未初始化的变量还存在其他可能的问题。正如PHP手册中所说

在将一个文件包含到另一个使用相同变量名称的文件的情况下,依赖未初始化变量的默认值是有问题的。

这意味着变量可能会从包含的文件中获取一个值,并且将使用此值,而不是期望访问未初始化的变量,这可能会导致不可预知的结果。为了避免这种情况,最好在使用前初始化 PHP 文件中的所有变量。null

处理该问题的方法:

  1. 推荐:在使用前声明每个变量。这样,只有当你真正犯了一个错误,试图使用一个不存在的变量时,你才会看到这个错误--这就是这个错误消息存在的原因。

     //Initializing a variable
     $value = ""; //Initialization value; 0 for int, [] for array, etc.
     echo $value; // no error
     echo $vaule; // an error pinpoints a misspelled variable name
    
  • 定义了变量但在函数中不可见的特殊情况。PHP 中的函数有自己的变量作用域,如果需要在函数中使用外部变量,则必须将其值作为函数的参数传递:

    function test($param) {
        return $param + 1; 
    }
    $var = 0;
    echo test($var); // now $var's value is accessible inside through $param
    
  1. 使用 null 合并运算符抑制错误。但请记住,这样 PHP 将无法通知您使用错误的变量名称。

     // Null coalescing operator
     echo $value ?? '';
    

    对于古老的 PHP 版本(< 7.0),可以使用带有三元的 isset()

     echo isset($value) ? $value : '';
    

    请注意,它本质上仍然是一种错误抑制,尽管只针对一个特定错误。因此,它可能会阻止 PHP 通过标记一个单一化变量来帮助您。

  2. 使用 @ 运算符禁止显示错误。出于历史原因留在这里,但说真的,这不应该发生。

注意:强烈建议仅实现第 1 点。

注意:未定义的索引 / 未定义的偏移量 / 警告:未定义的数组键

当您(或 PHP)尝试访问数组的未定义索引时,会出现此通知/警告。

内部阵列

在处理代码中定义的内部数组时,态度应该完全相同:只需在使用前初始化所有键即可。这样,这个错误就会完成它预期的工作:通知程序员他们的代码中的错误。所以方法是一样的:

推荐:声明数组元素:

    //Initializing a variable
    $array['value'] = ""; //Initialization value; 0 for int, [] for array, etc.
    echo $array['value']; // no error
    echo $array['vaule']; // an error indicates a misspelled key

一种特殊情况是当某个函数返回数组或其他值(如 或 )时。然后,在尝试访问数组元素之前必须对其进行测试,例如nullfalse

$row = $stmt->fetch();
if ($row) { // the record was found and can be worked with
    echo $row['name']; 
}

外部阵列

对于外部数组(例如//或JSON输入),情况略有不同,因为程序员无法控制此类数组的内容。因此,检查某些键是否存在,甚至为缺少的键分配默认值可能是合理的。$_POST$_GET$_SESSION

  • 当PHP脚本包含HTML表单时,在第一次加载时没有表单内容是很自然的。因此,这样的脚本应该检查表单是否已提交

      // for POST forms check the request method
      if ($_SERVER['REQUEST_METHOD'] === 'POST') {
          // process the form
      }
      // for GET forms / links check the important field
      if (isset($_GET['search'])) {
          // process the form
      }
    
  • 如果未选中某些 HTML 表单元素(如复选框),则不会发送到服务器。在这种情况下,使用空合并运算符来分配默认值是合理的

      $agreed = $_POST['terms'] ?? false;
    
  • 可选的 QUERY STRING 元素或 cookie 应以相同的方式处理

      $limit = $_GET['limit'] ?? 20;
      $theme = $_COOKIE['theme'] ?? 'light';
    

但是作业应该在脚本的一开始就完成。验证所有输入,将其分配给局部变量,并在代码中一直使用它们。因此,你要访问的每个变量都会故意存在。

相关:

评论

10赞 IMSoP 10/25/2013
@dieselpower44 几点想法:“关闭运算符”() 存在一些性能问题。此外,由于它禁止特定范围内的所有错误,因此不小心使用它可能会掩盖您希望看到的消息。@
6赞 Salman A 9/13/2014
隐藏问题不是处理问题的方法。项目 #2...#4 只能在生产服务器上使用,而不能在一般情况下使用。
1赞 Slava 10/11/2014
当还使用自定义错误处理程序时,是否可以关闭内联消息(而不是在处理程序中)? 仍然引起注意..$var = @$_GET['nonexisting'];
21赞 forsvunnet 2/9/2015
为什么推荐使用 1. 而不是使用 4。?$value = isset($_POST['value']) ? $_POST['value'] : '';$value = @$_POST['value'];
2赞 M Rostami 11/18/2016
我不建议对数组使用 isset(),例如,(我知道它应该是数组)将返回 true。最好使用 array_key_exist() 而不是 isset()$str = '111';isset($str[0])
80赞 3 revsmario #5

错误显示 @ 运算符

对于不需要的和冗余的通知,可以使用专用的 @ 运算符来“隐藏”未定义的变量/索引消息。

$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_dumpprint_r 来验证所有输入数组的当前内容:

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

    两者都将显示您的脚本是使用正确的还是任何参数调用的。

  • 或者,或者另外使用浏览器开发工具F12 并检查网络选项卡中的请求和参数:

    browser developer tools / network tab

    POST 参数和 GET 输入将单独显示。

  • 对于参数,您还可以查看 QUERY_STRING$_GET

    print_r($_SERVER);
    

    PHP 有一些规则将非标准参数名称合并到超全局变量中。Apache 也可能会做一些重写。 您还可以以这种方式查看提供的原始标头和其他 HTTP 请求标头。$_COOKIES

  • 更明显地,查看浏览器地址栏的 GET 参数

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

    问号后面的对是查询 (GET) 参数。因此,此 URL 只能产生 和 。name=value?$_GET["id"]$_GET["sort"]

  • 最后,检查您的 <form> 和 <input> 声明,如果您需要一个参数但没有收到任何参数。

    • 确保每个必需的输入都有一个<input name=FOO>
    • or 属性是不够的。id=title=
    • 表单应该填充 。method=POST$_POST
    • 而 a(或省略它)会产生变量。method=GET$_GET
    • 表单也可以通过 _GET 美元提供,其余字段以 _POST 美元为单位。action=script.php?get=parammethod=POST
    • 在现代PHP配置(≥5.6)中,再次使用$_REQUEST['vars']变得可行(不时髦),它混合了GET和POST参数。
  • 如果您正在使用 mod_rewrite,那么您应该同时检查并启用 RewriteLog 以找出缺失的参数。access.log

$_FILES

  • 相同的健全性检查适用于文件上传和 .$_FILES["formname"]
  • 此外,检查enctype=multipart/form-data
  • 以及您的声明。method=POST<form>
  • Смотритетакже: PHP 未定义索引错误 $_FILES?

$_COOKIE

  • 该数组永远不会在 之后立即填充,而只会在任何后续的 HTTP 请求上填充。$_COOKIEsetcookie()
  • 此外,它们的有效性超时,它们可能受到子域或单个路径的约束,用户和浏览器可以拒绝或删除它们。

评论

2赞 Gajus 2/11/2014
如果你很好奇性能影响是什么,这篇文章总结得很好,derickrethans.nl/......
0赞 mario 2/11/2014
@GajusKuizinas 自 2009 年以来,已经发生了一些变化,特别是 php.net/ChangeLog-5.php#5.4.0 结果发生了巨大变化(参见“Zend Engine,性能”和“(静音)运算符”)。
0赞 Gajus 2/12/2014
谢谢@mario,有趣。现在,如果有人足够好,可以对两者进行基准测试......3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs 根据这个测试,似乎是相同的(注意比例变化)。
38赞 2 revs, 2 users 80%Ferenci Zoltán László #6

我不想禁用通知,因为它很有帮助,但我想避免过多的输入。

我的解决方案是这个函数:

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') ?>

评论

2赞 skierpage 6/20/2012
您的 ifexists() 函数在 PHP 5.3 中对我不起作用。调用方的变量在函数的局部作用域中不可用(请参阅变量作用域),除非它们是超全局变量或您摆弄$GLOBALS,否则通常将返回 null。(斜体字为 php.net 章。$foo = "BABAR"; ifexists('foo');
0赞 gcb 7/9/2013
现在你会得到“你好”......重点是什么?只需检查值if( !empty($user) and !empty($location) ) echo "hello $user ..."
31赞 3 revs, 3 users 43%Peter Mortensen #7

这是因为变量“$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;
17赞 3 revs, 2 users 73%user2253362 #8

我使用我自己有用的函数 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;
}
11赞 2 revs, 2 users 75%gts #9

保持简单:

<?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 the array index. Nice
?>
25赞 2 revs, 2 users 57%Shahin Mammadzada #10

快速解决方法是将代码顶部的变量赋值为 null:

$user_location = null;
31赞 2 revs, 2 users 92%mpyw #11

获取输入字符串的最佳方式是:

$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');
20赞 rybo111 #12

我曾经诅咒过这个错误,但提醒你转义用户输入可能会有所帮助。

例如,如果您认为这是聪明的,那么速记代码:

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

...再想想!更好的解决方案是:

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

(我使用自定义功能转义字符,您的里程可能会有所不同)html()

15赞 2 revs, 2 users 60%Rishabh Seth #13

用一种非常简单的语言

错误是你使用的变量不是你之前定义的,它没有任何价值。因此,我建议您在使用之前声明此变量。例如:$user_location


$user_location = '';

$user_location = 'Los Angles';

这是您可能会遇到的一个非常常见的错误。所以别担心;只需声明变量并享受编码

30赞 Robbie #14

在回答“”为什么它们突然出现?我曾经使用这个脚本很多年了,我从来没有遇到过任何问题。

对于大多数网站来说,在“显示所有错误,但不显示'通知'和'已弃用'”的“默认”错误报告下运行是很常见的。这将在 php.ini 中设置并应用于服务器上的所有站点。这意味着示例中使用的那些“通知”将被抑制(隐藏),而其他被认为更严重的错误将被显示/记录。

另一个关键设置是可以隐藏错误(即 设置为“off”或“syslog”)。display_errors

在这种情况下,将发生的情况是,要么将设置更改为同时显示通知(如示例所示),要么将设置更改为在屏幕上(而不是禁止显示/记录它们)。error_reportingdisplay_errors

他们为什么会改变?

显而易见/最简单的答案是有人在php.ini中调整了这些设置,或者PHP的升级版本现在使用与以前不同的php.ini。这是第一个要看的地方。

但是,也可以在

  • .htconf(Web 服务器配置,包括虚拟主机和子配置)*
  • .htaccess域名
  • 在PHP代码本身中

这些中的任何一个也可以改变。

还有一个额外的复杂性,即 Web 服务器配置可以启用/禁用 .htaccess 指令,因此,如果您在 .htaccess 中有突然启动/停止工作的指令,那么您需要检查它。

(.htconf / .htaccess 假设您以 Apache 身份运行。如果运行命令行,这将不适用;如果运行 IIS 或其他 Web 服务器,则需要相应地检查这些配置)

总结

  • 检查 php.ini 中的 php 指令没有更改,或者您没有使用与以前不同的 php.ini。error_reportingdisplay_errors
  • .htconf(或vhosts等)中的check和php指令没有改变error_reportingdisplay_errors
  • .htaccess 中的 check 和 php 指令未更改error_reportingdisplay_errors
  • 如果 .htaccess 中有指令,请检查 .htconf 文件中是否仍然允许使用它们
  • 最后检查你的代码;可能是一个不相关的库;查看是否在那里设置了 PHP 指令。error_reportingdisplay_errors

评论

0赞 xdhmoore 11/18/2020
我们经历了与此类似的行为变化,这是由于代码中的自定义行为与我们以前不知道的自定义行为不同。error_reportingerror_handler
7赞 Wouter de Winter #15

关于这部分问题:

为什么它们会突然出现?我曾经使用这个脚本多年,我从来没有遇到过任何问题。

没有明确的答案,但这里有一些可能的解释,说明为什么设置会“突然”改变:

  1. 您已将 PHP 升级到较新的版本,该版本可以具有其他默认值,用于error_reporting、display_errors或其他相关设置。

  2. 您删除或引入了一些代码(可能在依赖项中),这些代码在运行时使用 或(在代码中搜索这些设置)设置相关设置ini_set()error_reporting()

  3. 您更改了 Web 服务器配置(此处假设为 apache):文件和虚拟主机配置也可以操作 php 设置。.htaccess

  4. 通常通知不会显示/报告(参见PHP手册) 因此,在设置服务器时,由于某种原因(文件权限??),可能无法加载php.ini文件,并且您处于默认设置。后来,“错误”已经解决了(意外),现在它可以加载正确的php.ini文件,并将error_reporting设置为显示通知。

24赞 5 revs, 3 users 83%smcjones #16

为什么会这样?

随着时间的流逝,PHP已经成为一种更加注重安全的语言。以前默认关闭的设置现在默认打开。一个完美的例子是 ,从 PHP 5.4.0 开始默认打开。E_STRICT

此外,根据PHP文档,默认情况下,在php.ini文件中被禁用。PHP 文档建议将其打开以进行调试。但是,当我从 Ubuntu 存储库和 BitNami 的 Windows 堆栈下载 PHP 时,我看到了其他东西。E_NOTICE

; 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

请注意,它实际上默认设置为生产值,而不是默认设置为“默认”值。这有点令人困惑,并且在 php.ini 之外没有记录,所以我没有在其他发行版上验证这一点。error_reporting

但是,为了回答您的问题,此错误现在会弹出,而之前没有弹出,因为:

  1. 您安装了 PHP,新的默认设置记录得有些少,但不排除 .E_NOTICE

  2. E_NOTICE像未定义的变量和未定义的索引这样的警告实际上有助于使你的代码更简洁、更安全。我可以告诉你,几年前,保持启用迫使我声明我的变量。它使学习 C 变得容易得多。在 C 语言中,不声明变量是一件大事。E_NOTICE

我能做些什么?

  1. 通过复制“默认值”并将其替换为等于登录后当前未注释的值来关闭。重新启动 Apache,如果使用 CGI 或 FPM,请重新启动 PHP。确保您正在编辑“正确的”php.ini 文件。如果您使用 Apache 运行 PHP,正确的选择是 Apache,如果运行 PHP-FPM,则为 fpm 或 php-fpm,如果运行 PHP-CGI,则为 cgi,等等。这不是推荐的方法,但如果您的遗留代码将非常难以编辑,那么它可能是您最好的选择。E_NOTICEE_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDerror_reporting =

  2. 在文件或文件夹级别关闭。如果您有一些遗留代码,但希望以“正确”的方式做事,这可能更可取。为此,您应该咨询 Apache 2、Nginx 或您选择的任何服务器。在 Apache 中,您可以在 .E_NOTICEphp_value<Directory>

  3. 重写代码以使其更简洁。如果您需要在迁移到生产环境时执行此操作,或者不希望有人看到您的错误,请确保禁用任何错误显示,并且只记录您的错误(请参阅 和 php.ini 和您的服务器设置)。display_errorslog_errors

扩展选项 3:这是理想的选择。如果你能走这条路,你应该走。如果最初不走这条路线,请考虑通过在开发环境中测试代码来最终移动这条路线。当你在做的时候,摆脱并看看将来可能出什么问题。你会看到很多不熟悉的错误,但当你将来需要升级PHP时,它会阻止你遇到任何不愉快的问题。~E_STRICT~E_DEPRECATED

错误是什么意思?

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;

另一种选择是在函数顶部声明一个空数组。这并不总是可能的。

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

//...

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

(附加提示)

  • 当我遇到这些问题和其他问题时,我使用了 NetBeanss IDE(免费),它给了我许多警告和通知。其中一些提供了非常有用的提示。这不是必需的,除了大型项目外,我不再使用 IDE。这些天我更像是一个人,:)。vim
20赞 2 revs, 2 users 76%elpiel #17

在 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

评论

0赞 a coder 2/24/2018
这在 if 语句中也有效。if (is_array($my_array['idontexist'] ?? '')) { dosomething(); }
0赞 elpiel 2/26/2018
你的代码实际上是一个被忽视的好错误:??- 仅检查 ,如果通过 - 这是一个布尔值,则会出现意外行为。isset()is_array()
9赞 3 revs, 3 users 73%Sinte #18

未定义的索引是指在数组中请求不可用的数组索引。例如

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

未定义的变量意味着您完全没有使用现有变量,或者未由该名称定义或初始化。例如

<?php print_r($myvar); ?>

未定义的偏移量意味着在数组中,您要求输入一个不存在的键。解决方案是在使用前检查:

php> echo array_key_exists(1, $myarray);

评论

0赞 Peter Mortensen 9/20/2021
“php>”表示什么?某种 REPL?如果是,是哪一个?
5赞 2 revsJohn Conde #19

如果使用类,则需要确保使用以下命令引用成员变量:$this

class Person
{
    protected $firstName;
    protected $lastName;

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

        // Incorrect
        $lastName = $last;

        // Incorrect
        $this->$lastName = $last;
    }
}
4赞 3 revsFred -ii- #20

引发未定义索引通知的另一个原因是数据库查询中省略了列。

即:

$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的问答:

-1赞 2 revs, 2 users 71%Peter Mortensen #21

可能您一直在使用旧的PHP版本,直到现在升级了PHP,这就是它多年来一直在没有任何错误的情况下工作的原因。

在 PHP 4 之前,如果您在未定义变量的情况下使用变量,则不会出现错误,但从 PHP 5 开始,它会为所提到的代码抛出错误。

-3赞 2 revs, 2 users 88%Funk Forty Niner #22

在处理文件时,需要正确的 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>";

?>

参考:

-2赞 Andrei Todorut #23

这些通知是因为你没有使用的变量,并且键没有出现在变量中。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)
-3赞 2 revs, 2 users 73%Manish Goswami #24

在 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 if the variable is defined or undefined
// Isset() does not check that variable has a true or false value
// But it checks the null value of a variable
if(isset($my_variable_name)){

}

简单解释

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

// It will check if the variable is defined or not and if the variable has a null value.
if(isset($unDefineVariable)){
    echo "true";
}else{
    echo "false";
}
4赞 2 revs, 2 users 98%John Conde #25

提交HTML表单后变量不存在的一个常见原因是表单元素不包含在标记中:<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>
7赞 2 revs, 2 users 82%James #26

使用三元运算符简单、可读且干净:

PHP 7

将一个变量分配给另一个变量的值(如果已设置),否则赋值(或您需要的任何默认值):null

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

菲律宾比索 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 值来标识确切状态。

如果您只关心错误日志中没有通知,那么作为一种选择,您可以简单地忽略错误日志。

0赞 Jaime Montoya #27

我问了一个关于这个问题的问题,我被推荐到这个帖子,并附有以下消息:

这个问题在这里已经有答案了:

“注意:未定义的变量”、“注意:未定义的索引”和“注意: 未定义的偏移量“使用 PHP

我在这里分享我的问题和解决方案:

这是错误:

enter image description here

第 154 行是问题所在。这是我在第 154 行的内容:

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

我认为问题是我正在为变量编写 if 条件,这不是键而是 中的值。首先,您能否确认这是否是警告的原因?其次,如果这是问题所在,为什么我不能根据值编写条件?是否必须使用我需要写入条件的密钥?$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)){
2赞 3 revs, 3 users 88%Pupil #28

每当我们使用未设置的变量时,就会发生这些错误。

处理这些问题的最佳方法是在开发时设置错误报告。

要设置错误报告,请执行以下操作:

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

在生产服务器上,错误报告处于关闭状态,因此,我们不会收到这些错误。

但是,在开发服务器上,我们可以设置错误报告。

为了摆脱这个错误,我们看到以下示例:

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

我们可以在赋值或使用变量之前初始化变量。NULL

因此,我们可以将代码修改为:

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

这不会干扰任何程序逻辑,即使没有值也不会生成通知。$test

因此,基本上,最好为开发设置错误报告。

并修复所有错误。

在生产环境中,错误报告应设置为关闭。

-1赞 2 revs, 2 users 62%NAVNEET CHANDAN #29

如果要向 API 发送数据,只需使用 isset():

if(isset($_POST['param'])){
    $param = $_POST['param'];
} else {
    # Do something else
}

如果错误是由会话引起的,请确保您已正确启动会话。

评论

0赞 Peter Mortensen 9/20/2021
API 的示例是什么?你指的是什么?你能详细说明一下吗?