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

Posted

技术标签:

【中文标题】“注意:未定义的变量”、“注意:未定义的索引”、“警告:未定义的数组键”和“注意:未定义的偏移量”使用 PHP【英文标题】:"Notice: Undefined variable", "Notice: Undefined index", "Warning: Undefined array key", and "Notice: Undefined offset" using PHP 【发布时间】:2017-12-17 08:30:42 【问题描述】:

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

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

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

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

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

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

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

为什么会突然出现?这个脚本我用了很多年,从来没有遇到过问题。

我该如何解决?


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

相关元讨论:

What can be done about repetitive questions? Do “reference questions” make sense?

【问题讨论】:

Reference - What does this error mean in PHP?的可能重复 变量可能尚未初始化。您是从 post 或 get 或任何数组初始化变量吗?如果是这种情况,您可能在该数组中没有字段。您的访问权限。 @Pekka웃 - 我注意到编辑添加了“和”注意:未定义的偏移量“” - 使用“PHP:“未定义的变量”、“未定义的索引”、“未定义的偏移量“通知”(甚至取出 PHP,因为它被标记为“php”。另外,URL 在and-notice-undef 处被截断,只是一个建议,以便 URL 不会被截断。甚至可以删除(太多)引号。或PHP: “Undefined variable/index/offset” notices @Fred 我想可以为这两种变体提出一个论据。新手有可能会输入整行,包括“通知:”到他们的搜索查询中,我确信这是这个问题的主要流量生成器。如果消息完整,这可能会提高在搜索引擎中的可见度 @Pekka웃 我明白了。我之所以这么说,是因为 URL 之前没有被截断,现在它在 and-notice-undef 处截断。这只是一个(几个)建议。它只是重复自己也是Notice: Undefined 【参考方案1】:

注意/警告:未定义变量

来自PHP Manual的浩瀚智慧:

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

来自PHP documentation:

如果变量不存在,则不会生成警告。这意味着 empty() 本质上是 !isset($var) || 的简洁等价物。 $var == 错误

这意味着您只能使用 empty() 来确定变量是否已设置,此外它还会根据以下内容检查变量:00.0"""0"、@987654347 @、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";
);

在3v4l.org online PHP editor中测试上面的sn-p

虽然 PHP 不需要变量声明,但它确实建议使用它以避免一些安全漏洞或错误,即人们会忘记为稍后将在脚本中使用的变量赋值。 PHP 在未声明变量的情况下所做的是发出一个非常低级的错误,E_NOTICE,默认情况下甚至不会报告这个错误,而是在开发过程中使用手册 advises to allow。

处理问题的方法:

    推荐:声明您的变量,例如当您尝试将字符串附加到未定义的变量时。或者使用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 operator:

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';

    为 E_NOTICE 设置custom error handler 并将消息从标准输出重定向(可能到日志文件):

    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');
    //or
    list($one, $two) = explode(',', 'test string');
    

两个变量用于访问两个数组元素,但是数组元素只有一个,索引0,所以会生成:

注意:未定义的偏移量:1

#$_POST/$_GET/$_SESSION变量

上述通知在使用$_POST$_GET$_SESSION 时经常出现。对于$_POST$_GET,您只需在使用它们之前检查索引是否存在。对于$_SESSION,您必须确保会话以session_start() 开始,并且索引也存在。

还要注意所有 3 个变量都是 superglobals 并且是大写的。

相关:

Notice: Undefined variable Notice: Undefined Index

【讨论】:

@dieselpower44 一些想法:“闭嘴操作员”(@) 存在一些性能问题。此外,由于它会抑制特定范围内的 所有 错误,因此不小心使用它可能会掩盖您希望看到的消息。 隐藏问题不是处理问题的方法。项目 #2...#4 只能在生产服务器上使用,不能在一般情况下使用。 是否可以在使用自定义错误处理程序时关闭消息内联(不在处理程序中)? $var = @$_GET['nonexisting']; 仍然引起注意.. 为什么推荐使用1.$value = isset($_POST['value']) ? $_POST['value'] : '';而不是4.$value = @$_POST['value']; 我不建议对数组使用 isset(),例如$str = '111';,(我知道它应该是数组)isset($str[0]) 将返回 true。最好使用 array_key_exist() 而不是 isset()【参考方案2】:

试试这些

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(); 需要放在所有使用会话的文件中。

http://php.net/manual/en/features.sessions.php

【讨论】:

如果使用php.ini配置文件中的E_NOTICE,请执行error_reporting = (E_ALL & ~E_NOTICE) This answer is being discussed on meta. 从上面的答案中,我尝试了 isset、array_key_exists ,但这些都不起作用。我试过你的答案,.empty(),它有效。非常感谢!【参考方案3】:

错误显示@ operator

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

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

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

替代或另外使用您的browser devtools (F12) 并检查网络选项卡中的请求和参数:

POST 参数和 GET 输入将分开显示。

$_GET参数你也可以在QUERY_STRING里偷看

print_r($_SERVER);

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

更明显地查看GET parameters的浏览器地址栏:

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 变量。 表单还可以通过 $_GET 提供 action=script.php?get=param 并在 $_POST 旁边提供剩余的 method=POST 字段。 使用现代 PHP 配置 (≥ 5.6),再次使用 $_REQUEST['vars'] 已成为 feasible(不流行),它混合了 GET 和 POST 参数。

如果您使用 mod_rewrite,则应同时检查 access.log 并启用 RewriteLog 以找出缺少的参数。

$_FILES

同样的健全性检查适用于文件上传和$_FILES["formname"]。 另外检查enctype=multipart/form-data 以及您的<form> 声明中的method=POST。 另见:PHP Undefined index error $_FILES?

$_COOKIE

$_COOKIE 数组永远不会在 setcookie() 之后立即填充,而只会在任何后续 HTTP 请求中填充。 此外,它们的有效性超时,它们可能被限制为子域或单个路径,用户和浏览器可以拒绝或删除它们。

【讨论】:

如果你好奇对性能有什么影响,这篇文章总结的很好,derickrethans.nl/…。 @GajusKuizinas 自 2009 年以来发生了一些变化,特别是 php.net/ChangeLog-5.php#5.4.0 极大地改变了结果(请参阅“Zend 引擎,性能”和“(静音)运算符”)。 谢谢@mario,很有趣。现在,如果有人足以对两者进行基准测试... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs 根据这个测试,似乎是相同的(注意规模变化)。【参考方案4】:

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

    如果是错误,请先正确分配变量:$varname=0; 如果确实只是有时定义,请在使用前对其进行测试:if (isset($varname)) 如果是因为您拼写错误,请更正 甚至可以关闭你的警告PHP-settings

【讨论】:

请不要关闭警告。在更严格的语言中,它们通常意味着“可能存在错误,您最好检查此行两次”——在像 PHP 这样宽松的语言中,它们通常意味着“这段代码很垃圾,并且可能充满了错误;我会尽量让有点感觉,但你最好尽快解决这个问题”。 虽然我同意前三点,但#4 是完全错误的。隐藏问题不会让它消失,甚至可能会导致更多问题。 @Freek 绝对正确,但在某些情况下(购买脚本,零技术知识,明天需要它运行......)这是胶带解决方案 - 真的很糟糕,总是需要强调,但是一个选项【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

您的 ifexists() 函数在 PHP 5.3 中对我不起作用。调用者的变量在函数的局部范围内不可用(参见 变量范围),除非它们是 Superglobals 或者你摆弄 $GLOBALS,所以$foo = "BABAR"; ifexists('foo'); 通常会返回 null。 (斜体为 php.net 章节。) 现在你会得到“你好”......有什么意义?只需检查值if( !empty($user) and !empty($location) ) echo "hello $user ..."【参考方案7】:

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

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

【讨论】:

【参考方案8】:

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

【讨论】:

【参考方案9】:

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

大多数网站在“显示所有错误,但不是'通知'和'已弃用'”的“默认”错误报告下运行是很常见的。这将在 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 指令是否已设置在那里。

【讨论】:

我们经历了与此类似的行为变化,这是由于 error_reporting 的行为与预期不同,因为我们的代码中有一个我们以前不知道的自定义 error_handler【参考方案10】:

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

$user_location = null;

【讨论】:

【参考方案11】:

为什么会这样?

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

此外,根据 PHP 文档,默认情况下,E_NOTICE 在文件 php.ini 中被禁用。 PHP 文档推荐turning it on for debugging purposes。然而,当我从 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 之外没有记录,所以我 not 在其他发行版上对此进行了验证。

然而,为了回答你的问题,这个错误之前没有弹出,现在弹出,因为:

    您安装了 PHP,但新的默认设置记录不充分,但不排除 E_NOTICE

    E_NOTICE 未定义变量和未定义索引等警告实际上有助于使您的代码更清洁、更安全。我可以告诉你,几年前,启用E_NOTICE 迫使我声明我的变量。它让学习 C 变得容易了很多。在 C 中,不声明变量更麻烦。

我该怎么办?

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

    在文件或文件夹级别关闭E_NOTICE。如果您有一些遗留代码但想要以“正确”的方式做事,这可能会更可取。为此,您应该咨询 Apache 2、nginx 或任何您选择的服务器。在 Apache 中,您可以在 &lt;Directory&gt; 中使用 php_value

    重写您的代码以使其更简洁。如果您在迁移到生产环境时需要执行此操作,或者不想让别人看到您的错误,请确保您禁用任何错误显示,并且只记录您的错误(请参阅display_errorslog_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';

(附加提示)

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

【讨论】:

【参考方案12】:

我曾经诅咒这个错误,但提醒您避开用户输入会很有帮助。

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

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

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

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

(我使用自定义的html()函数来转义字符,你的里程可能会有所不同)

【讨论】:

【参考方案13】:

在 PHP 7.0 中,现在可以使用 null coalescing operator:

echo "My index value is: " . ($my_array["my_index"] ?? '');

等于:

echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');

PHP manual PHP 7.0

【讨论】:

这在 if 语句中也可以正常工作。 if (is_array($my_array['idontexist'] ?? '')) dosomething(); 您的代码实际上是一个很好的被忽视的错误:?? - 只检查isset(),如果你通过is_array() - 这是一个布尔值,会出现意外行为。【参考方案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;

【讨论】:

【参考方案15】:

用非常简单的语言

错误是您使用了一个变量$user_location ,它没有由您之前定义,并且它没有任何值。所以我建议你声明这个变量之前 使用它。例如:


$user_location = '';$user_location = 'Los Angles';

这是您可能面临的一个非常常见的错误。所以不用担心;只需声明变量并享受编码

【讨论】:

【参考方案16】:

保持简单:

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

【讨论】:

【参考方案17】:

未定义的索引意味着您请求的数组中的数组索引不可用。例如,

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

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

<?php print_r($myvar); ?>

未定义的偏移量表示您要求的数组中的键不存在。解决方法是在使用前进行检查:

php> echo array_key_exists(1, $myarray);

【讨论】:

“php>”是什么信号?某种REPL?如果有,是哪一个?【参考方案18】:

关于这部分问题:

为什么会突然出现?这个脚本我用了很多年,从来没有遇到过问题。

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

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

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

    您更改了 webserver 配置(假设这里是 apache):.htaccess 文件和 vhost 配置也可以操纵 php 设置。

    通常不会显示/报告通知(请参阅PHP manual) 所以有可能在设置服务器时,由于某种原因(文件权限??)无法加载 php.ini 文件,而您使用的是默认设置。后来,“错误”已被解决(偶然),现在它可以加载正确的 php.ini 文件,并将 error_reporting 设置为显示通知。

【讨论】:

【参考方案19】:

使用ternary operator 简单、易读且干净:

Pre PHP 7

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

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

PHP 7+

除了使用null coalescing operator 外,其他相同。不再需要调用isset(),因为它是内置的,并且不需要提供要返回的变量,因为它假定返回正在检查的变量的值:

$newVariable = $thePotentialData ?? null;

Both 将停止 OP 问题中的 Notices,并且 both 完全等同于:

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 通知或降低您的错误报告级别,但它不能解决问题。它只是停止在错误日志中报告它。这意味着您的代码仍在尝试使用未设置的变量,这可能意味着也可能不意味着某些东西无法按预期工作 - 取决于缺失值的重要性。

你真的应该检查这个问题并适当地处理它,或者提供不同的消息,或者甚至只是为其他所有内容返回一个空值来识别精确的状态。

如果您只关心通知不在错误日志中,那么您可以选择忽略错误日志。

【讨论】:

【参考方案20】:

如果使用类,您需要确保使用 $this 引用成员变量:

class Person

    protected $firstName;
    protected $lastName;

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

        // Incorrect
        $lastName = $last;

        // Incorrect
        $this->$lastName = $last;
    

【讨论】:

【参考方案21】:

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

即:

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

Are table names in mysql case sensitive?

mysql case sensitive table names in queries

MySql - Case Sensitive issue of tables in different server

【讨论】:

【参考方案22】:

HTML 表单提交后变量不存在的一个常见原因是表单元素未包含在&lt;form&gt; 标记中:

示例:&lt;form&gt; 中不包含元素

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

示例:元素现在包含在 &lt;form&gt;

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

【讨论】:

【参考方案23】:

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

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

设置错误报告:

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 没有值也不会产生通知。

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

并修复所有错误。

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

【讨论】:

【参考方案24】:

我问了一个关于这个的问题,然后我被推荐到这篇文章中,并附有以下信息:

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

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

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

这是错误:

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

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

我认为问题在于我正在为变量$city 编写if 条件,这不是键而是$key =&gt; $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))

【讨论】:

【参考方案25】:

可能您之前一直在使用旧的 PHP 版本,现在升级了 PHP,这就是它多年来一直运行没有任何错误的原因。

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

【讨论】:

【参考方案26】:

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

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

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

【讨论】:

什么是 API 示例?你指的是什么?你能详细说明一下吗?【参考方案27】:

这些通知是因为您没有使用的变量 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)

【讨论】:

【参考方案28】:

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

?>

参考:

POST method uploads

【讨论】:

【参考方案29】:

在 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";

【讨论】:

以上是关于“注意:未定义的变量”、“注意:未定义的索引”、“警告:未定义的数组键”和“注意:未定义的偏移量”使用 PHP的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

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

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