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

注意:未定义变量my_variable_name在C:\wamp\www\mypath\index.php第10行 注意:第11行未定义索引:my_index C:\wamp\www\mypath\index.php 警告:在C:\wamp\www\mypath\index.php第11行未定义数组键“my_index”

第10和11行是这样的:

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

这些错误消息的含义是什么?

为什么他们会突然出现?我曾经使用这个脚本多年,从来没有任何问题。

我该如何修复它们?


这是一个一般参考问题,供人们链接作为副本,而不是需要一遍又一遍地解释这个问题。我觉得这很有必要,因为现实世界中关于这个问题的答案都非常具体。 相关元讨论: 如何应对重复的问题? “参考问题”有意义吗?


当前回答

在PHP 7.0中,现在可以使用空合并操作符:

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

Is等于:

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

PHP 7.0手册

其他回答

为什么会这样?

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

此外,根据PHP文档,默认情况下,E_NOTICE在PHP .ini文件中是禁用的。PHP文档建议为了调试目的打开它。然而,当我从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实际上默认设置为生产值,而不是默认设置为“default”值。这有点令人困惑,并且在php.ini之外没有记录,所以我没有在其他发行版上验证这一点。

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

您安装了PHP,新的默认设置的文档很少,但不排除E_NOTICE。 E_NOTICE警告,如未定义变量和未定义索引,实际上有助于使您的代码更干净和更安全。我可以告诉你,几年前,保持E_NOTICE启用迫使我声明我的变量。在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。 重写代码,使其更清晰。如果你在转移到生产环境时需要这样做,或者不想让别人看到你的错误,确保你禁用了任何错误显示,只记录你的错误(参见php.ini和你的服务器设置中的display_errors和log_errors)。

扩展选项3:这是最理想的。如果你可以走这条路,你就应该走。如果您最初没有走这条路,请考虑最终通过在开发环境中测试您的代码来移动这条路。在此过程中,去掉~E_STRICT和~E_DEPRECATED,看看将来会出现什么问题。您将看到许多不熟悉的错误,但这将使您在将来需要升级PHP时避免遇到任何不愉快的问题。

这些错误意味着什么?

未定义变量:my_variable_name—当变量在使用前没有定义时,会发生这种情况。当PHP脚本执行时,它在内部只假定一个空值。但是,在哪种情况下需要在定义变量之前检查它呢?归根结底,这是对“草率代码”的论证。作为一名开发人员,我可以告诉您,当我看到一个开源项目在其作用域中尽可能高地定义变量时,我非常喜欢。它可以更容易地判断将来会弹出哪些变量,也可以更容易地阅读/学习代码。

function foo()
{
    $my_variable_name = '';

    //....

    if ($my_variable_name) {
        // perform some logic
    }
}

未定义索引: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';

(额外的小费)

当我遇到这些和其他问题时,我使用了netbeans IDE(免费),它给了我许多警告和注意。其中一些提供了非常有用的建议。这不是一个要求,除了大型项目,我不再使用ide了。我现在更有活力了:)。

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

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

在处理文件时,需要适当的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方法上传

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

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

一个未定义的变量意味着你完全没有使用一个现有的变量,或者这个变量没有定义或初始化。例如,

<?php print_r($myvar); ?>

未定义的偏移量意味着在数组中请求一个不存在的键。解决这个问题的方法是在使用前检查:

php> echo array_key_exists(1, $myarray);

HTML表单提交后变量不存在的一个常见原因是表单元素没有包含在<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 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>