在PHP中如何最好地与0进行比较?

14

我正在处理的一段代码中,需要从数据库中提取一个值并检查它是否为0。最初,我将其编写为:

if ($myVal == 0) { ...

但是今天我重新查看代码后,发现那里有一个 bug:

var_dump("foo" == 0);  // bool(true)

// and while we're here...
var_dump(intval("foo")); // int(0)

由于这个值来自数据库,那通常意味着它会是一个字符串,因此我想我可以这样做:

if ($myVal === "0")

但这似乎不符合直觉,因为我实际上想处理整数,而这似乎表明我们正在处理字符串。(希望你能理解。) 此外,任何给定的DB访问器将把值转换为其适当的类型,这应该是意料之中的,考虑到字段类型。

当值既可能是字符串又可能是整数时,你使用什么方法来检查其是否为0?


1
+1 看起来很基础,但考虑到 PHP 的类型转换,这是一个令人惊讶的有趣问题。 - cletus
7个回答

22
简短版本:
if ("$myVal" === '0')
或者
if (strval($myVal) === '0')

Long version:

if ($myVal === 0 || $myVal === '0')

1
哦,这很聪明 - 我没想到可以这样转换! - nickf
1
我的猜测是长版本实际上更快。"===" 是快速比较,因为它不进行类型转换。 - jmucchiello
@Jm:你可能是对的。只是打起来更麻烦而已。 :) - cletus
1
我刚刚进行了一些基准测试:就运行时间而言,你的strval()方法与我提出的is_numeric函数基本相同(执行100,000次迭代需要0.31秒)。然而,使用"$myVal" === 0方法要快6-7倍,而长版本则要快10倍以上! - nickf
我对"$myVal"比strval()慢这一点感到非常惊讶。我原以为结果会恰好相反。有趣的测试结果。 - cletus

2
我目前能提供的最佳翻译是这样的:

我的最佳解决方案是:

is_numeric($myVal) && $myVal == 0

这个条件将始终返回false,因为正如您在问题中所说,从数据库返回的值是字符串。 $myVal是一个字符串,比较将在此停止。 在进行比较之前,您应该将您的值转换为整数。 - Boris Guéry
1
实际上,is_numeric() 函数将会对一个数值字符串返回 true。请参考 http://au2.php.net/is_numeric。 - thomasrutter

1

如果从数据库中获取的值是字符串,但原始数据类型是整数,则您可能希望您的DAO(数据访问对象或提取数据的任何其他对象)将事物转换为您期望的数据类型。这样,查看值的PHP代码就会查看它所期望的数据类型。

问题在于,当然,DB定义的数据类型与PHP定义的数据类型之间没有一对一的对应关系。但是,大多数情况下,这不是问题,因为对于我们通常使用的大多数类型,都有等效的类型:int、float、bool、string。

总之,在查询数据库的地方和检查这些值的地方之间,这些值应该被转换为您期望的数据类型。我刚刚在一个包含int(10)和varchar(50)的MySQL表上使用mysql_fetch_object()进行了测试;PHP始终将两个字段作为“string”类型拉入。因此,如果您想要将其中一个字段视为int,请在对其执行任何操作之前将其转换为int。例如:

$rs = mysql_query("SELECT * FROM table");
while ($row = mysql_fetch_object($rs)) {
    $RealRow->id = (int)$row->id;
    $RealRow->name = $row->name;
    // etc.
}

// ... later ...

if ($RealRow->status == 0) {
    // do something
}

查询和`RealRow`的内容应该放在一个类/方法中,这样它就被封装起来了;这样,你的代码中任何从`table`获取数据的部分都将始终获取`$RealRow`对象,该对象将对所有内容设置为正确的数据类型。当然,如果你更改了数据类型,则需要手动编辑DAO以处理强制转换;也可以查询数据库以获取每个字段的类型(使用“SHOW COLUMNS FROM table”),并自动将字段强制转换为适当的数据类型。

"SHOW FULL COLUMNS FROM myTable" 命令是一种更简单的方式来确定每个字段的数据类型。然而,有时候这种抽象层次对于特定情况来说可能过于复杂。 - nickf
我更喜欢如果“SHOW [FULL] COLUMNS”可以将数据类型按基本类型、显示空间、无符号等分成单独的字段,以便更易于编程地访问。目前,您必须手动解析输出的“Type”字段...虽然我相信有人已经为此编写了库。 - dirtside

1

我认为你应该只使用

if ($myVal == 0)

我认为不必担心 $myVal 是否为 "foo"。你自己说过,这个值只会是一个数字。

换句话说,如果你发现 $myVal 是 "foo",那么 bug 不是 "foo" == 0,而是 $myVal 应该是一个数字,但却是 "foo"。


0
// In codeigniter 3.1.11
if( $row->mamt === 0 || $row->mamt === '0')
{
    $temp    =   'C'.++$set_flag;

    $this->db->where('sch_code',$row->sch_code);
    $this->db->where('inst_no',$row->inst_no);
    $this->db->update($this->fl_karvy, array('flag' => $temp));
}

0
if( ('integer' === gettype($is_anonymous) && $is_anonymous === 0 )
    ||
    ('string' === gettype($is_anonymous) && $is_anonymous === '0')    
 ) {
    echo 'matches';
}

虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - Jay Blanchard

0
尝试使用intval()将字符串转换为整数。
if( intval($myVal) == 0 )

4
(intval("this shouldn't equal zero") == 0)为真。 - nickf
将字符串转换为整数,除非该字符串以数字开头,否则结果为0。字符串“foo”转换为0,字符串“35foo”转换为35。 - dirtside

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接