在 PHP 中,为啥 mysqli_num_rows 不为返回行数为 0 的查询返回整数?

Posted

技术标签:

【中文标题】在 PHP 中,为啥 mysqli_num_rows 不为返回行数为 0 的查询返回整数?【英文标题】:In PHP, why doesn't mysqli_num_rows return an integer for a query with 0 returned rows?在 PHP 中,为什么 mysqli_num_rows 不为返回行数为 0 的查询返回整数? 【发布时间】:2019-03-03 23:59:05 【问题描述】:

我对 mysqli_num_rows 有一个奇怪的问题。在搜索这个问题时,我只发现有人遇到无论如何都会返回 NULL 的问题。我还检查了official documentation 的函数,它说它返回查询返回的行数的整数。每当我的查询返回 1 行(它永远不应该返回更多)时,它的行为都符合我的预期。当查询返回 0 行时,我希望函数返回 0,但它返回 NULL。为什么不返回 0?

我知道我的数据库连接良好并且我的查询工作正常,因为当我在数据库中查找记录时,我得到一个整数。我只是不明白为什么返回 NULL 而不是 0。

function getArtistID($name) 
    global $conn; 
    $query = "SELECT artist_id FROM artist WHERE artist_name LIKE '$name'";
    $result = mysqli_query($conn, $query);
    if ($result->num_rows) 
        $row = mysqli_fetch_assoc($result);
        return $row['artist_id'];
     else 
        return 0;
    

【问题讨论】:

你怎么知道的?鉴于此代码,无论它返回 0 还是 null 的行为应该是相同的。我有一种感觉,mysqli_query 是返回 null 的那个,而不是 mysqli_num_rows 不要使用global。如果您的代码需要,这清楚地表明设计不佳。 @tkausl 是的,这是真的。但我很好奇为什么它不返回 0。文档没有提到它返回 NULL。 真的相信您误解了某些信息。如果它真的返回null,请说明你是如何得出这个结论的,包括任何带有var_dumps的代码和相应的输出。 人们常说使用global不好,因为它很难编写单元测试。如果函数引用全局变量,则不能在有限范围内测试函数。为全局变量创建模拟对象很尴尬。见phpunit.readthedocs.io/en/8.0/fixtures.html#global-state 【参考方案1】:

这是我用来重现 num_rows 似乎为 NULL 的情况的一些代码:

<?php
error_reporting(E_ALL);
$conn = new mysqli('127.0.0.1', 'root', null, 'test');
$sql = "SELECT * FROM dual";
$result = $conn->query($sql);
if ($result === false) 
  print "Error: $conn->error\n";

$n = $result->num_rows;
echo "Dump the num_rows property: ";
var_dump($n);

输出:

Error: No tables used

Notice: Trying to get property of non-object in /Users/bkarwin/Documents/SO/my.php on line 14
Dump the num_rows property: NULL

该通知是因为访问不是对象的变量的面向对象的属性是无效的。这对于 PHP 开发人员来说是一个常见的混淆源,它是 PHP 是一种松散类型语言这一事实​​的副产品,像 query() 这样的函数可以返回 结果对象或布尔标量.

query() 函数实际上返回了一个 false 作为$result 因为一些错误。在我的代码中,我检查了这个错误,而你没有。

当您运行mysqli::query()mysqli::prepare()mysqli_stmt::execute() 时,您必须每次检查错误情况。

关于您的查询的某些内容导致了错误。由您来检查错误并报告它。


更新:我编辑了上面的一些文本以使解释更好,但这可能会使下面的一些 cmets 显得格格不入。

【讨论】:

好的,我会添加支票。但是当我在 phpmyadmin 中运行查询时,我没有收到任何错误。我也,当它返回行时不会有任何奇怪的行为。我的表确实有列。我不太明白你的意思。 我的查询只是生成错误的查询示例之一。我是说您的查询可能会产生一些不同的错误。关键是您没有检查错误。 我猜你也没有调用error_reporting() 来启用通知,当$result 是布尔值false 时你应该调用$result-&gt;num_rows。除非它是一个对象,否则您不能从变量请求面向对象的属性。当变量是标量时,您应该在正确配置错误报告级别时收到通知。这在我的代码示例中显示。 当你不配置 PHP 输出通知,并且你不自己检查错误时,你会得到很多令人困惑的效果,因为你不知道什么时候发生了错误。 PHP 开发者学习phptherightway.com 并实践所有建议应该是必读。【参考方案2】:

我只是想不通为什么返回 NULL 而不是 0。

看不到日志输出,我们只能猜测;但是,返回值很可能是 null,因为它引发了错误。

在尝试使用返回值之前,您需要确保在调用函数时处理了错误。

【讨论】:

以上是关于在 PHP 中,为啥 mysqli_num_rows 不为返回行数为 0 的查询返回整数?的主要内容,如果未能解决你的问题,请参考以下文章

php显示报错: Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given

PHP操作数据库出现错误:mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in

mysqli_num_rows() 期望参数通过同一页面上的较早查询有效

INSERT 查询产生“警告:mysqli_num_rows() 期望参数 1 为 mysqli_result,给定布尔值”

警告:mysqli_num_rows() 期望参数 1 为 mysqli_result,bool 给定...我该怎么办? [复制]

如何在mysql中选择前三行