【问题标题】:Weak typing in PHP: why use isset at all?PHP 中的弱输入:为什么要使用 isset?
【发布时间】:2009-01-05 17:53:29
【问题描述】:

如果我这样做,我的代码似乎可以检查 null

if ($tx) 

if (isset($tx))

为什么写第二个比较难?

【问题讨论】:

  • 我在这里有一个非常相似的问题 - stackoverflow.com/questions/413928/… - 我也会关注你的答案。
  • @Bryan,我认为这是 PHP 的一个问题:从经验上讲,一切正常,但在实践中,您必须非常小心并提出所有这些问题。我也会看你的……
  • 人生有3种做事方式;有效的方式,无效的方式以及正确运作的方式。仅仅工作的东西和正确工作的方式之间有很大的区别。这是从糟糕/有缺陷的代码转变为优秀代码的开始。
  • @TravisO,或者只是转移到编译器不允许使用错误/错误代码的语言,例如 Java 或 C#。你不会弄错它,因为它不会编译,如果它编译它就不会运行。我的意思是,主要是...... :)

标签: php syntax


【解决方案1】:
if ($tx)

对于以下任何条件,此代码将评估为 false:

unset($tx); // not set, will also produce E_WARNING
$tx = null;
$tx = 0;
$tx = '0';
$tx = false;
$tx = array();

下面的代码只会在以下条件下评估为假:

if (isset($tx))

// False under following conditions:
unset($tx); // not set, no warning produced
$tx = null;

对于某些人来说,打字非常重要。但是,PHP 在设计上对变量类型非常灵活。这就是创建Variable Handling Functions 的原因。

【讨论】:

  • 取消设置永远不会发出通知或警告
  • 糟糕,我的意思是如果你稍后在变量上运行if ($tx),它会抛出警告。
【解决方案2】:

isset() 与 TYPE 或 VALUE 无关 - 仅与 EXISTENCE 相关。

if ($condition)... 将 VALUE OF THE VARIABLE 评估为布尔值。

if ( isset($condition) )... 将 EXISTENCE OF THE VARIABLE VALUE 评估为布尔值。

isset() 可能为假有两个原因。

首先,因为变量没有设置,所以没有值。

其次,因为一个变量是NULL,这意味着“未知值”,不能被认为是设置,因为它包含“无值”,而且因为很多人使用$v = null来表示与unset($五)。

(请记住,如果您特别想检查 null,请使用 is_null()。)

isset() 通常用于检查可能存在或不存在的外部变量。

例如,如果您有一个名为 page.php 的页面,它有:

ini_set('display_errors', 1);
error_reporting(E_ALL);

if ( $_GET["val"] ) {
    // Do Something
} else {
    // Do Nothing
}

它适用于以下任何 URL:

http://www.example.com/page.php?val=true // Something will be done.
http://www.example.com/page.php?val=monkey // Something will be done.

http://www.example.com/page.php?val=false  // Nothing will be done.
http://www.example.com/page.php?val=0// Nothing will be done.

但是,您将收到此 URL 的错误:

http://www.example.com/page.php

因为 URL 中没有 'val' 参数,所以 $_GET 数组中没有 'val' 索引。

正确的做法是这样的:

if ( isset($_GET["val"]) ) {
    if ( $_GET["val"] ) {
        // Do Something
    } else {
        // Do Nothing
    }
} else {
    // $_GET["value"] variable doesn't exist.  It is neither true, nor false, nor null (unknown value), but would cause an error if evaluated as boolean.
}

虽然这有捷径。

您可以使用empty()检查存在和某些布尔条件的组合,

if ( !empty($_GET["val"]) ) {
    // Do someting if the val is both set and not empty
    // See http://php.net/empty for details on what is considered empty
    // Note that null is considered empty.
}

if ( isset($_GET["val"]) and $_GET["val"] ) {
    // Do something if $_GET is set and evaluates to true.
    // See php.net logical operators page for precedence details,
    // but the second conditional will never be checked (and therefor
    // cause no error) if the isset returns false.
}

【讨论】:

  • 这个答案对想要了解差异的人非常有帮助。谢谢!
  • 但是在以后的分析中,您只考虑了 PHP 处理器(在 GET 上)没有设置变量或者您没有将其用作用户的简单情况。但是对象可以为空,函数可以返回空等,正如 chazomaticus 指出的那样......现在,如果我可以将两个答案标记为最佳......
  • 更新了——有没有人觉得这个措辞有点搞笑?
【解决方案3】:

我想指出,我在这里阅读的每个人的回复都应该添加一个警告:

“如果测试已设置为 NULL 的变量,isset() 将返回 FALSE” (php.net/isset)。

这意味着在 某些 情况下,例如检查 GET 或 POST 参数,使用 isset() 足以判断变量是否已设置(因为它要么是字符串,要么是不会设置)。但是,如果 NULL 是变量的可能值,这在您进入对象和更复杂的应用程序时很常见,isset() 会让您感到兴奋和枯燥。

例如(使用 PHP 5.2.6 和 Suhosin-Patch 0.9.6.2 (cli) 测试(构建时间:2008 年 8 月 17 日 09:05:31)):

<?php
$a = '';
$b = NULL;
var_dump(isset($a));
var_dump(isset($b));
var_dump(isset($c));

输出:

bool(true)
bool(false)
bool(false)

谢谢,PHP!

【讨论】:

  • 您会在谁的答案中添加警告?大多数答案不是已经提到了吗?
  • Eli 和 Eran Galperin 的,特别是。 Eli:“如果 $condition 变量存在,则 isset() 为真,无论其值如何。”除非值为 NULL。 Eran Galperin:“第二次检查 (isset()) 测试变量是否存在。”只要变量的值不为 NULL。
【解决方案4】:

简单地说,这些比较是不一样的。第一个将变量转换为布尔值,这将无法检查空数组、非数字字符串和其他检查,其中明确设置了变量。第二个检查(isset())测试变量是否存在。

如果不检查变量的类型,我永远不会执行第一次检查(布尔转换)。

更不用说,第一次检查会抛出 E_NOTICE,而且我总是以最大错误报告级别运行。

【讨论】:

  • 空数组!?好吧,我没有考虑这些东西。感谢您的回答!
  • "exists at all" 是不对的,正如 chazomaticus 指出的那样:变量可能被设置为 null,所以它们存在......
  • isset 对于 null 但设置变量返回 true。仅对未设置的变量返回 false
【解决方案5】:

第一个仅根据您的服务器配置方式起作用。在许多生产服务器上,它会中断。

使用isset() 并快乐。

或者,在 PHP 源代码的顶部尝试使用以下代码并观察它的中断:

ini_set('display_errors', 1);
error_reporting(E_ALL);

【讨论】:

  • 同意。哪些配置属性会导致它崩溃?
  • 它不会破坏任何东西,但会抛出 E_NOTICE 类型错误(不会停止脚本执行)。
  • 感谢 Triptych 的回答和更新。这是一个很好的观点,尽管我认为大多数生产服务器实际上对错误报告没有那么严格。
【解决方案6】:

因为前者还可以检查真/假,您可能想要也可能不想要。

【讨论】:

    【解决方案7】:

    因为第一个会产生警告,如果$tx === false也会返回true,和没定义不一样

    【讨论】:

    【解决方案8】:

    正如每个答案都指出的那样,这两者完全不同。如果你不使用 isset,很多东西都会被评估为 false,尤其是数组、false 值、0(和其他)的数值等。确实如此。

    我觉得很奇怪,每个人都这么快地捍卫正确 PHP 编程。如果我想做正确的编程,我有大量的静态类型、强类型语言可以使用。在我看来,PHP 的一个优点是我不必过多考虑类型。当然,在某些情况下,

    if ($tx)
    

    当它确实有一个值时评估为 false,但是如果你想检查 它是否是一个事务对象,它要么有效,要么无效。原来,有了 Doctrine 框架,这段代码

    if (isset($tx))
    

    在获取查询的第一个对象后总是评估为真。我不得不说

    if ($tx instanceof PurchaseRecord)
    

    所以我的意思是,在 PHP 中,你知道你在测试什么!例如,如果它是来自 GET 请求的参数,那么它将为 null、空或有值。你必须处理这三种情况。或者两个案例,或者您在特定代码中拥有的任何数量的案例。 一旦你有了,如果它可以在你的开发服务器上运行并且它在你的生产服务器上运行,也许你可以说它可以正常工作并继续你的生活?

    (在 Java 或 C# 中,它必须编译然后运行而不会抛出异常。Java 中的大多数 NullPointer 异常实际上都会被抛出而不会引起任何问题:Java API 不可能检查代码中的所有空值,因为这是不可能的,而且因为没问题。如果它编译并按预期工作,你就知道你的代码没问题。然后你可以担心抛出更多正确的异常。)

    如果您在任何时候都必须知道 PHP 中代码的底层类型,为什么不首先使用类型进行编码呢?或者更重要的是,为什么不利用 PHP 的松散性和运行代码的代码。

    【讨论】:

      【解决方案9】:

      还需要注意的是,PHP 中的字符串可以设置但为空。因此即使字符串中没有任何内容,isset 也会返回 true,为了防止这种情况,我使用类似这样的函数来替换 isset:

      <?php
          function exists($var) {
              if (isset($var) && $var != "") {
                  return true;
              } else {
                  return false;
              }
          }
      ?>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-29
        • 2022-12-29
        • 1970-01-01
        • 2011-06-01
        • 1970-01-01
        • 2011-11-03
        • 2014-01-02
        相关资源
        最近更新 更多