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

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

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

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

第 10 和 11 行看起来像这样:

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

这些错误消息是什么意思?

为什么它们突然出现?我曾经使用此脚本多年,但从未遇到任何问题。

我该如何解决?


这是一个供人们链接为重复的通用参考问题 ,而不必一遍又一遍地解释该问题。我认为这是必要的,因为有关此问题的大多数实际答案都是非常具体的。

相关元讨论:

答案

注意:未定义的变量

PHP 手册的广泛智慧中:

在将一个文件包含在另一个使用相同变量名的文件中的情况下,依靠未初始化变量的默认值是有问题的。启用register_globals也是主要的安全风险 。如果使用未初始化的变量,则会发出E_NOTICE级错误,但是如果将元素附加到未初始化的数组,则不会发出E_NOTICE级错误。 isset()语言构造可用于检测变量是否已初始化。另外,更理想的方法是empty()的解决方案,因为如果未初始化变量,它不会生成警告或错误消息。

PHP 文档

如果变量不存在,则不会生成警告。这意味着empty()本质上与!isset($ var)||等效。 $ var == false

这意味着,可以使用仅empty()以确定是否变量设置,并且另外它检查变量对以下, 00.0"""0"nullfalse[]

例:

$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 不需要变量声明,但它确实推荐这样做,以避免某些安全漏洞或 bug,因为这些漏洞或 bug 可能会忘记为变量提供值,该变量将在脚本的后面使用。在未声明变量的情况下,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 合并运算符

    // 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 个变量都是超全局变量,并且都是大写的。

有关:

试试这些

问题 1:此通知表示未在脚本的当前作用域中定义 $ varname。

问题 2:在使用任何可疑变量之前,使用 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);

关于会话的注意事项:

错误显示@运算符

对于不想要的和多余的通知,可以使用专用的@运算符 » 隐藏 « 未定义的变量 / 索引消息。

$var = @($_GET["optional_param"]);

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

  1. 如果输入错误,请先为变量进行适当的赋值:$ varname = 0;
  2. 如果确实只是有时定义了它,请对其进行测试: if (isset($varname)) ,然后再使用它
  3. 如果是因为您拼写错误,请更正
  4. 甚至在您的PHP 设置中打开警告

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

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

我的解决方案是此功能:

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

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

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

这是因为未定义变量 '$ 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;

回答 “”,为什么它们突然出现?我曾经使用此脚本多年,而且从未遇到任何问题。”

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

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

在这种情况下将发生的情况是,要么将error_reporting更改为还显示通知(根据示例),并且 / 或者将设置更改为在屏幕上显示为display_errors (而不是抑制 / 记录它们)。

为什么要改变?

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

但是,也可以覆盖这些设置

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

并且其中任何一个都可能已经更改。

Web 服务器配置可以启用 / 禁用. htaccess 指令还增加了复杂性,因此,如果您在. htaccess 中有突然启动 / 停止工作的指令,则需要进行检查。

(.htconf / .htaccess 假定您正在以 apache 身份运行。如果运行命令行则不适用;如果运行 IIS 或其他网络服务器,则需要相应地检查那些配置)

摘要

  • 检查 php.ini 中的error_reportingdisplay_errors php 指令没有更改,或者您没有使用与以前不同的 php.ini。
  • 检查. htconf(或虚拟主机等)中的error_reportingdisplay_errors php 指令是否已更改
  • 检查. htaccess 中的error_reportingdisplay_errors php 指令未更改
  • 如果您在. htaccess 中有指令,请检查. htconf 文件中是否仍然允许使用它们
  • 最后检查您的代码;可能是无关的库;查看是否在此处设置了error_reportingdisplay_errors php 指令。

快速的解决方法是在代码顶部将变量分配为 null

$user_location = null;