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级别的错误,但不会在将元素追加到未初始化的数组的情况下发生。 isset()语言结构可用于检测变量是否已被初始化。 此外,更理想的是empty()的解决方案,因为如果变量未初始化,它不会生成警告或错误消息。
从PHP文档:
如果变量不存在,则不会生成警告。 这意味着empty()实质上就是!isset($ var)||的简洁等价物 $ var == false 。
这意味着您只能使用empty()
来确定变量是否已设置,并且此变量将根据以下值检查变量0,"",null
。
例:
$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不需要变量声明,但为了避免一些安全漏洞或错误,人们会忘记给稍后在脚本中使用的变量赋予一个值。 在未声明变量的情况下,PHP会发出一个非常低的错误, E_NOTICE
,默认情况下甚至没有报告,但手册建议在开发过程中允许。
处理这个问题的方法:
推荐:声明你的变量,例如当你试图将一个字符串附加到一个未定义的变量时。 或者使用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操作符:
// Null coalesce operator - No need to explicitly initialize the variable.
$value = $_POST['value'] ?? '';
为E_NOTICE设置自定义错误处理程序,并将消息从标准输出(可能是日志文件)中重定向:
set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
禁止报告E_NOTICE。 排除E_NOTICE
快速方法是:
error_reporting( error_reporting() & ~E_NOTICE )
用@运算符来抑制错误。
注意:强烈建议仅实施第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个变量都是超全球变量。 这意味着他们需要用大写字母书写。
有关:
试试这些
Q1:此通知表示$ varname未在脚本的当前范围内定义。
Q2:在使用任何可疑变量之前,使用isset(),empty()条件很好。
// recommended solution
$user_name = $_SESSION['user_name'];
if (empty($user_name)) $user_name = '';
OR
// just define at the top of the script index.php
$user_name = '';
$user_name = $_SESSION['user_name'];
OR
$user_name = $_SESSION['user_name'];
if (!isset($user_name)) $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
一个(通常不鼓励)的选择是错误抑制运算符@
。 它是关闭不需要的通知和警告的特定语言结构,但应小心使用。
首先,它在使用isset
时会导致微观性能损失。 这在现实世界的应用中是不可测量的,但应该在数据大量迭代中考虑。 其次,它可能阻碍调试,但同时抑制错误实际上传递给自定义错误处理程序(与isset装饰表达式不同)。
上一篇: PHP: "Notice: Undefined variable", "Notice: Undefined index", and "Notice: Undefined offset"