“注意:未定义的变量”、“注意:未定义的索引”、“警告:未定义的数组键”和“注意:未定义的偏移量”使用 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()
来确定变量是否已设置,此外它还会根据以下内容检查变量:0
、0.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?"];
其次,如果通知没有明显的原因,请使用var_dump
或print_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_reporting
和 display_errors
php 指令没有更改,或者您没有使用与以前不同的 php.ini。
检查 .htconf(或虚拟主机等)中的 error_reporting
和 display_errors
php 指令没有改变
检查.htaccess 中的error_reporting
和display_errors
php 指令没有改变
如果 .htaccess 中有指令,请检查 .htconf 文件中是否仍然允许它们
最后检查你的代码;可能是一个不相关的图书馆;查看error_reporting
和display_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 & ~E_NOTICE & ~E_STRICT & ~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 中,您可以在 <Directory>
中使用 php_value
。
重写您的代码以使其更简洁。如果您在迁移到生产环境时需要执行此操作,或者不想让别人看到您的错误,请确保您禁用任何错误显示,并且只记录您的错误(请参阅display_errors
和 log_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 表单提交后变量不存在的一个常见原因是表单元素未包含在<form>
标记中:
示例:<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>
【讨论】:
【参考方案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 => $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】:这些通知是因为您没有使用的变量 defined
和 my_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