PHP 中的 Null 对 False 对0

有人告诉我,好的开发人员能够发现/利用 NullFalse0以及所有其他好的“无”实体之间的差异。
有什么不同,特别是在 PHP 中? 它与 ===有什么关系吗?

166593 次浏览

这些值之间的差异总是归结为特定于语言的详细规则。对于 Python、 Perl 或 C 等等,您从 PHP 中学到的东西并不一定是正确的。虽然学习你正在使用的语言的规则是有价值的,但过分依赖它们是自找麻烦。当下一个程序员需要维护您的代码时,麻烦就来了,您已经使用了一些结构,这些结构利用了 Null 与 False 的一些小细节(例如)。您的代码应该看起来正确(相反,错误的代码应该看起来是错误的)。

Null 是空值,False 是一位,0(可能)是32位。

不是 PHP 专家,但在一些更现代的语言中,这些是不可互换的。我有点怀念0和 false 是可互换的,但是布尔型是一个实际的类型,你可以有方法和对象与它相关联,所以这只是一个折衷。但是,Null 是 Null,即本质上没有任何内容。

False、 Null、 Nothing、0、 UnDefinition 等等。

其中每一个都有与实际概念相关的特定含义。有时候,多个含义被重载到单个关键字或值中。

CC + + 中,NULLFalse0被重载为相同的值。 在 C # 中,它们是三个不同的概念。

nullNULL通常表示缺乏价值,但通常没有说明原因。 0表示自然数为零,与 一,二,三,等具有类型等价性,在支持单独的 NULL概念的语言中,应该只处理一个数字。

False 表示非真相。在 二进制值中使用。它不意味着未设置,也不意味着 0。它只表示两个二进制值中的一个。

没有任何东西可以表明该值被特别设置为没有,这表明同样的事情为空,但意图。

在某些语言中未定义表示该值尚未设置,因为没有代码指定实际值。

在数据库中使用 Null 表示“没有记录”或“没有信息”。所以你可能有一个比特字段来描述“这个用户想不想被我们发送电子邮件”,其中 True 意味着他们想,False 意味着他们不想被发送任何东西,但是 Null 意味着你不知道。它们可以通过外部连接处等等来到。

NULL 的逻辑含义通常是不同的——在某些语言中,NULL 不等于任何值,所以如果(a = = NULL)总是为 false。

所以个人而言,我总是将一个布尔值初始化为 FALSE,而将一个布尔值初始化为 NULL 看起来有点讨厌(即使在 C 语言中,两个布尔值都是0... ... 只是一种样式)。

好吧,我在 PHP 的时候记不太清楚“ = = =”这部分,但是对于大多数 C 风格的语言,NULL 应该在指针值的上下文中使用,false 作为布尔值,0作为整数这样的数值。“0”是字符上下文的惯用值。对于 float 和 double,我通常也喜欢使用0.0。

所以,快速回答是: 背景。

在 PHP 中,这取决于是否验证类型:

(
( false !== 0 ) && ( false !== -1 ) && ( false == 0 ) && ( false == -1 ) &&
( false !== null ) && ( false == null )
)

技术上无效是 0x00,但在 PHP ( null == 0x00 ) && ( null !== 0x00 )

0是一个整数值。

我认为糟糕的开发人员会在代码中发现 null/0/false 的各种不同用法。

例如,开发人员最常犯的错误之一就是以函数的数据形式返回错误代码。

// On error GetChar returns -1
int GetChar()

这是一个糖接口的例子。这在《调试软件开发过程》一书和另一本《编写正确的代码》一书中都有解释。

这样做的问题在于对字符类型的暗示或假设。在某些编译器上,字符类型可以是无符号的。所以即使返回 -1,编译器也可以返回1。在 C + + 或 C 中,这种编译器假设很难被发现。

相反,最好的方法是不要将错误代码与数据混在一起。

char GetChar()

现在变成了

// On success return 1
// on failure return 0
bool GetChar(int &char)

这意味着无论开发人员在您的开发工作室中有多么年轻,他或她永远不会犯这个错误。尽管这并不是指代码中的冗余或依赖。

所以一般来说,交换 bool 作为语言中的第一类类型是可以的,我认为 Joel 在他最近的邮件中谈到了这一点。但是尽量不要在你的例程中使用混合和匹配的数据,你应该是完全没有问题的。

在几乎所有的现代语言中,null 逻辑上来说指没有值的指针(或引用) ,或者没有初始化的变量。0是0的整数值,false 是布尔值,好吧,false。为了使事情变得复杂,例如,在 C 中,null、0和 false 都以完全相同的方式表示。我不知道它在 PHP 中是如何工作的。

然后,更复杂的是,数据库有 null 的概念,这意味着缺少或不适用,大多数语言没有直接的方法将 DBNull 映射到它们的 null。例如,直到最近,int 为 null 和为0之间还没有区别,但是这种区别被可为 null 的 int 所改变。

抱歉让你觉得这很复杂。多年来,这一直是语言中的一个难点,直到最近,还没有任何明确的解决方案。人们过去常常只是把东西拼凑在一起,或者在数据库中使用空或0表示空值,这并不总是能很好地工作。

来自 PHP 在线文档:

若要显式地将值转换为布尔值,请使用(bool)或(boolean)强制转换。
但是,在大多数情况下,强制转换是不必要的,因为如果运算符、函数或控制结构需要布尔参数,则值将被自动转换。
当转换为布尔值时,下列值被认为是 FALSE:

  • 布尔型 FALSE本身
  • 整数“0(零)
  • 浮动 0.0(零)
  • 空字符串和字符串 "0"
  • 零元素的数组
  • 一个没有成员变量的对象(仅适用于 PHP4)
  • 特殊类型 NULL(包括未设置的变量)
  • 从空标记创建的 SimpleXML 对象
    每个其他值都被认为是 TRUE(包括任何资源)。

所以,在大多数情况下,都是一样的。

另一方面,=====不是一回事。通常,您只需要使用“ equals”运算符。澄清:

$a == $b    //Equal. TRUE if $a is equal to $b.
$a === $b   //Identical. TRUE if $a is equal to $b, and they are of the same type.

有关更多信息,请查看 PHP 在线文档中的“ 比较运算符”页面。

希望这个能帮上忙。

关于在 PHP 中使用 NULL的一个有趣的事实是: 如果将一个 var 设置为 NULL,那么这与在其上调用 unset()是相同的。

NULL本质上意味着变量没有赋值; false是一个有效的布尔值,0是一个有效的整数值,PHP 在 0"0"""false之间有一些相当丑陋的转换。

False 和0在概念上是相似的,即它们是同构的。0是自然数代数的初始值,False 是布尔代数的初始值。

换句话说,0可以被定义为一个数,当把它加到某个自然数上时,得到相同的数:

x + 0 = x

类似地,False 是这样一个值,它与任何其他值的分离都是同一个值:

x || False = x

Null 在概念上是完全不同的东西。根据不同的语言,它有不同的语义,但是它们都没有将“初始值”描述为 False 和0。Null 没有代数。它适用于变量,通常表示变量在当前上下文中没有特定的值。在大多数语言中,没有在 Null 上定义任何操作,并且使用 Null 作为操作数是一个错误。在某些语言中,有一个称为“ bottom”的特殊值,而不是“ null”,后者是计算值的占位符,不会终止。

关于 NULL 在其他地方的含义,我已经写了更多的文章。

在 PHP 中可以使用 = = 和!= = 运算符不仅检查值是否相等,而且检查它们的类型是否匹配。例如: 0 == falsetrue,而 0 === falsefalse!=!==也是如此。另外,如果您使用上面提到的运算符将 null与其他两个运算符进行比较,预计也会得到类似的结果。

现在在 PHP 中,这种值的质量通常用于返回值时,有时可以是 0(零) ,但有时可能是函数失败。在这种情况下,在 PHP 中返回 false,并且必须使用标识符 ===检查这些情况。例如,如果你正在搜索一个字符串在另一个字符串中的位置,而你正在使用 strpos(),这个函数将返回数字位置,如果字符串在最开始被找到,它可以是0,但是如果字符串根本没有被找到,那么 strpos()将返回 false,在处理结果时你必须考虑到这一点。

如果你在你的函数中使用相同的技术,任何熟悉这个 PHP标准库的人都会明白发生了什么,以及如何检查返回的值是否是你想要的,或者在处理过程中是否发生了错误。函数参数也是如此,你可以根据它们是数组还是字符串或者其他什么,对它们进行不同的处理,这种技术在 PHP 中也被广泛使用,所以每个人都很容易理解。所以我想这就是力量。

它是特定于语言的,但是在 PHP 中:

Null 表示“ 没什么”。 var 尚未初始化。

False 的意思是“ 在布尔上下文中不正确”。用于明确显示您正在处理逻辑问题。

0 是一个 int。和上面的其他部分没有关系,用于数学。

现在,棘手的是,在 PHP 等动态语言中,它们在布尔上下文中都有一个值(在 PHP 中)是 False

如果您使用 ==测试它,它将测试布尔值,因此您将得到相等的结果。如果您用 ===测试它,它将测试类型,您将得到不等式。

那么它们为什么有用呢?

看看 strrpos()函数。如果没有找到任何值,返回 False; 如果在字符串的开头找到了值,返回0!

<?php
// pitfall :
if (strrpos("Hello World", "Hello")) {
// never exectuted
}


// smart move :
if (strrpos("Hello World", "Hello") !== False) {
// that works !
}
?>

当然,如果你和国家打交道:

你想在 DebugMode = False(设置为关闭)、 DebugMode = True(设置为打开)和 DebugMode = Null(完全不设置,将导致难以调试; ——)之间做出区别。

nullnullfalsefalse。悲哀但真实。

PHP 没有太多的一致性(尽管它在最新版本的基础上有所改进,但有太多的向下兼容)。尽管设计希望有一些一致性(在这里选择的答案中概述) ,但是当您考虑以不那么容易推理的方式使用 false/null的方法返回时,一切都变得令人困惑。

当它们已经对某些内容使用 false 时,经常会看到使用 null。例如 filter _ input ()。如果变量使过滤器失败,则返回 false; 如果变量不存在,则返回 null (不存在意味着过滤器也失败了吗?)

当作者关心失败的类型时,可以交换返回 false/null/string/etc 的方法是一种技巧,例如,如果您关心验证失败的原因,那么使用 filter_input()可以检查 ===false===null。但是,如果您不这样做,那可能是一个陷阱,因为如果他们只记得为 ===false编写测试用例,那么他们可能会忘记为 ===null添加检查。而且大多数 php 单元测试/覆盖工具不会引起您对缺失的、未测试的代码路径的注意!

最后,这里有一些有趣的类型杂耍。甚至不包括数组或对象。

var_dump( 0<0 );        #bool(false)
var_dump( 1<0 );        #bool(false)
var_dump( -1<0 );       #bool(true)
var_dump( false<0 );    #bool(false)
var_dump( null<0 );     #bool(false)
var_dump( ''<0 );       #bool(false)
var_dump( 'a'<0 );      #bool(false)
echo "\n";
var_dump( !0 );        #bool(true)
var_dump( !1 );        #bool(false)
var_dump( !-1 );       #bool(false)
var_dump( !false );    #bool(true)
var_dump( !null );     #bool(true)
var_dump( !'' );       #bool(true)
var_dump( !'a' );      #bool(false)
echo "\n";
var_dump( false == 0 );        #bool(true)
var_dump( false == 1 );        #bool(false)
var_dump( false == -1 );       #bool(false)
var_dump( false == false );    #bool(true)
var_dump( false == null );     #bool(true)
var_dump( false == '' );       #bool(true)
var_dump( false == 'a' );      #bool(false)
echo "\n";
var_dump( null == 0 );        #bool(true)
var_dump( null == 1 );        #bool(false)
var_dump( null == -1 );       #bool(false)
var_dump( null == false );    #bool(true)
var_dump( null == null );     #bool(true)
var_dump( null == '' );       #bool(true)
var_dump( null == 'a' );      #bool(false)
echo "\n";
$a=0; var_dump( empty($a) );        #bool(true)
$a=1; var_dump( empty($a) );        #bool(false)
$a=-1; var_dump( empty($a) );       #bool(false)
$a=false; var_dump( empty($a) );    #bool(true)
$a=null; var_dump( empty($a) );     #bool(true)
$a=''; var_dump( empty($a) );       #bool(true)
$a='a'; var_dump( empty($a));      # bool(false)
echo "\n"; #new block suggested by @thehpi
var_dump( null < -1 ); #bool(true)
var_dump( null < 0 ); #bool(false)
var_dump( null < 1 ); #bool(true)
var_dump( -1 > true ); #bool(false)
var_dump( 0 > true ); #bool(false)
var_dump( 1 > true ); #bool(true)
var_dump( -1 > false ); #bool(true)
var_dump( 0 > false ); #bool(false)
var_dump( 1 > true ); #bool(true)

我刚刚浪费了1/2天试图得到一个 0nullfalse返回从 strops

在我发现这个逻辑没有朝正确的方向发展之前,我一直在努力做的就是这些,看起来就像是 PHP 编码中的一个黑洞:

概念 使用一个托管在服务器上的域名,并确保它不是根级别的,好的,有几种不同的方法可以做到这一点,但是我选择了不同的,因为我已经完成了其他的 php 函数/构造。

不管怎么说,这就是计算的基础:

if (strpos($_SERVER ['SERVER_NAME'], dirBaseNAME ())
{
do this
} else {
or that
}


{
echo strpos(mydomain.co.uk, mydomain);


if ( strpos(mydomain, xmas) == null )
{
echo "\n1 is null";
}


if ( (strpos(mydomain.co.uk, mydomain)) == 0 )
{
echo "\n2 is 0";
} else {
echo "\n2 Something is WRONG";
}


if ( (mydomain.co.uk, mydomain)) != 0 )
{
echo "\n3 is 0";
} else {
echo "\n3 it is not 0";
}


if ( (mydomain.co.uk, mydomain)) == null )
{
echo "\n4 is null";
} else {
echo "\n4 Something is WRONG";
}
}

读完这篇文章后, 我发现这个有用! ! !

{
if ((mydomain.co.uk, mydomain)) !== false )
{
echo "\n5 is True";
} else {
echo "\n5 is False";
}
}

感谢这篇文章,我现在明白了,即使它是圣诞节,它可能不是圣诞节作为 false,因为它也可以是一个 NULL的一天!

在浪费了一天时间调试一些简单的代码之后,真希望我以前就知道这个问题,因为我能够识别出问题,而不是到处去试图让它工作。它没有工作,因为 FalseNULL0不都是一样的作为 True or False or NULL

下面是一个例子:

            Comparisons of $x with PHP functions


Expression          gettype()   empty()     is_null()   isset() boolean : if($x)
$x = "";            string      TRUE        FALSE       TRUE    FALSE
$x = null;          NULL        TRUE        TRUE        FALSE   FALSE
var $x;             NULL        TRUE        TRUE        FALSE   FALSE
$x is undefined     NULL        TRUE        TRUE        FALSE   FALSE
$x = array();       array       TRUE        FALSE       TRUE    FALSE
$x = false;         boolean     TRUE        FALSE       TRUE    FALSE
$x = true;          boolean     FALSE       FALSE       TRUE    TRUE
$x = 1;             integer     FALSE       FALSE       TRUE    TRUE
$x = 42;            integer     FALSE       FALSE       TRUE    TRUE
$x = 0;             integer     TRUE        FALSE       TRUE    FALSE
$x = -1;            integer     FALSE       FALSE       TRUE    TRUE
$x = "1";           string      FALSE       FALSE       TRUE    TRUE
$x = "0";           string      TRUE        FALSE       TRUE    FALSE
$x = "-1";          string      FALSE       FALSE       TRUE    TRUE
$x = "php";         string      FALSE       FALSE       TRUE    TRUE
$x = "true";        string      FALSE       FALSE       TRUE    TRUE
$x = "false";       string      FALSE       FALSE       TRUE    TRUE

请参阅此文以获得更多关于 PHP 中 类型比较的参考资料。它应该会让您有一个清晰的理解。

虚假性的问题来自 PHP 的历史。问题的目标是定义不明确的标量类型。

'*' == true -> true (string match)
'*' === true -> false (numberic match)


(int)'*' == true -> false
(string)'*' == true -> true

PHP7的严格性是一个进步,但也许还不够

有人能解释一下为什么‘ NULL’不仅仅是比较实例中的字符串吗?

$x = 0;
var_dump($x == 'NULL');  # TRUE   !!!WTF!!!