PHP和未定义的变量策略

时间:2010-08-25 10:07:00

标签: php variables undefined

我是一名以PHP开头的C ++程序员。我发现由于未定义的变量,我失去了大部分调试时间(和我的自尊!)。据我所知,处理它们的唯一方法是在执行时观察输出。

其他策略是否注意到这些错误? (类似于C ++,单个编译为您提供了所需的所有线索)

感谢您的任何见解

12 个答案:

答案 0 :(得分:10)

这是PHP的常见抱怨。以下是一些想法:

  1. 使用code analysis tool。许多IDE(例如Netbeans)也会有所帮助。

  2. 只需运行代码。 PHP没有像C ++那样昂贵的编译步骤。

  3. 使用单元测试。常见的副作用包括:更好的代码。

  4. 设置error_reporting(-1)ini file中的等效内容。

  5. 获取xdebug。这不是预防性的,但堆栈跟踪有助于消除错误。

  6. isset()=== null(身份运营商)和警卫条款是您的朋友。

  7. 松散且动态的打字是该语言的一项功能。仅仅因为PHP isn't strict about typing并不意味着你不可能。如果它确实让你感到烦恼并且你有一个选择,那么你可以尝试使用Python - 它的输入更加严格。

答案 1 :(得分:6)

将您的E_NOTICE消息记录到文本文件中。然后,您可以使用自动脚本处理日志,以指示引发这些日志的文件和行。

答案 2 :(得分:5)

没有。在PHP中,当您尝试访问变量时,您只能知道变量不存在。

考虑:

if ($data = file('my_file.txt')) {
    if (count($data) >= 0)
        $line = reset($data);
}
var_dump($line);

您必须重新构建代码,以便所有代码路径都可以定义变量,例如:

$line = "default value";
if ($data = file('my_file.txt')) {
    if (count($data) >= 0)
        $line = reset($data);
}
var_dump($line);

如果没有任何默认值,这仍然优于isset,因为如果最终if中的变量名称中有拼写错误,您会发出警告:

$line = null;
if ($data = file('my_file.txt')) {
    if (count($data) >= 0)
        $line = reset($data);
}
if ($line !== null) { /* ... */ }

当然,您可以使用isset 1 在给定点检查变量是否存在。但是,如果您的代码依赖于此,那么它的结构可能很差。我的观点是,与例如在编译时,您不能确定对变量的访问是否有效。由于PHP中不存在块作用域,这会变得更糟。

1 严格来说,isset不会告诉您是否设置了变量,它会告诉您它是否已设置且不为空。否则,您需要get_defined_vars

答案 3 :(得分:2)

  

据我所知,处理它们的唯一方法是在执行时观察输出。

不是真的:为了防止这些通知弹出,您只需要确保在第一次访问变量之前初始化变量。我们(遗憾的是IMO)在PHP中没有变量声明,但是在代码块的开头初始化它们也是如此:

$my_var = value;

使用phpDocumentor语法,您也可以将它们声明为某种类型,至少以许多IDE能够使用以下方式进行代码查找:

/** @desc optional description of what the variable does
    @var int */
$my_var = 0;

此外,在尝试访问变量之前,您可以(有时需要)使用isset() / empty() / array_key_exists()条件。

I agree this sucks big time有时,但这是必要的。在完成的生产代码中应该没有通知 - 即使关闭显示它们也会消耗性能,而且它们对于找出使用变量时可能产生的拼写错误非常有用。 (但你已经知道了。)

答案 4 :(得分:2)

请注意不要在第一次使用时执行需要变量值的操作,例如concat operator。=

如果你是C ++程序员,你必须习惯于声明所有变量,在PHP中通过归零变量做一些与此类似的东西,或者如果你想使用变量就创建空数组。

注意用户输入,确保关闭了注册全局变量,并通过isset()检查来自$ _GET和$ _POST的输入。

您还可以尝试针对结构代码对类进行编码,并在类声明开始时使用正确的隐私策略创建每个变量。

您还可以通过准备所有必须首先输出的变量来分离应用程序逻辑和视图,当它显示它时,您将知道您准备了哪些变量。

答案 5 :(得分:2)

在开发阶段使用

error_reporting(E_ALL);

将显示导致的每个错误,所有NOTICE错误等等。

密切注意你的error_log,这将显示错误

使用错误报告系统,例如:

http://php.net/manual/en/function.set-error-handler.php

class ErrorReporter
{
    public function catch($errno, $errstr, $errfile, $errline)
    {
        if($errno == E_USER_NOTICE && !defined('DEBUG'))
        {
            //Catch all output buffer and clear states, redirect or include error page.
        }
    }
}

set_error_handler(array(new ErrorReporter,'catch'));

很少有其他提示总是使用isset表示您可能/可能没有设置的变量,因为if语句可以说。

始终使用if(isset($_POST['key']))或更好地使用if(!empty($_POST['key'])),因为这会检查密钥是否存在以及值是否为空。

确保你知道你的比较运算符,C#之类的语言使用==检查bool状态在php中检查数据类型你必须使用===并使用==检查值州和单=分配一个值!

答案 6 :(得分:2)

除非我遗漏某些内容,为什么没有人建议正确构建您的网页?我从未真正遇到过未定义变量错误的问题。

构建网页的想法

在顶部定义所有变量,必要时指定默认值,然后从那里使用这些变量。这就是我编写网页的方式,我从未遇到过未定义的变量问题。

不要只在你需要时定义变量的习惯,这很快会产生意大利面条代码,而且很难管理。

  

alt text

     

没有人喜欢spagehtti代码

如果您向我们展示了一些代码,我们可能会提供有关如何更好地构建代码以解决此类错误的建议。您可能会从C背景中感到困惑,流程可能与网页的工作方式不同。

答案 7 :(得分:1)

良好做法是在使用前定义所有变量,即设置默认值

  

$ variable = default_value;

这将解决大多数问题。正如之前所建议的那样,在Netbeans等编辑器中使用xdebug或内置调试工具

答案 8 :(得分:1)

如果要隐藏未定义变量的错误,请使用@。 例如:@$var

答案 9 :(得分:0)

我相信可用于PHP的各种代码覆盖率工具都会强调这一点。

答案 10 :(得分:0)

就个人而言,我尝试设置变量,即使它是一个空字符串,数组,布尔等。然后在使用之前使用isset()之类的函数。例如:

$page_found = false;

if ($page_found==false) {
    // do page not found stuff here
}

if (isset($_POST['field'])) {
    $value = $_POST['field'];
    $sql = "UPDATE table SET field = '$value'";
}

等等。在一些聪明的屁股说之前:我知道查询是不安全的。这只是使用isset()的一个例子。

答案 11 :(得分:0)

这是一个古老的问题,但是我确实在这里还没有找到直接的答案。我发现此问题的实际解决方案是使用PHP Code Sniffer以及称为PHP Code Sniffer Variable Analysis的出色扩展。

此外,常规PHP linter(php -l)也可在PHP Code Sniffer中使用,因此我正在考虑针对常规PHP linting定制我的配置,检测未使用/未初始化的变量并验证我自己的代码样式,这一切都需要一步完成。

编辑:我非常小的PHPCS配置:

<?xml version="1.0"?>
<ruleset name="MyConfig">
    <description>Minimal PHP Syntax check</description>
    <rule ref="Generic.PHP.Syntax" />
    <rule ref="VariableAnalysis" />
</ruleset>