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

Posted

技术标签:

【中文标题】“注意:未定义的变量”、“注意:未定义的索引”和“注意:未定义的偏移量”使用 PHP【英文标题】:"Notice: Undefined variable", "Notice: Undefined index", and "Notice: Undefined offset" using PHP 【发布时间】:2016-02-04 01:09:04 【问题描述】:

我正在运行 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"];

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

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

我该如何解决?


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

相关元讨论:

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

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

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

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

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

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

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

【讨论】:

【参考方案12】:

为什么会这样?

随着时间的推移,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 的人:)。

【讨论】:

【参考方案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