为什么`mysqli_query()`返回null?我该如何找出原因?

7
在某些情况下,PHP内置函数mysqli_query返回null。这种行为并未在函数文档中提到,因此我尝试深入研究PHP源代码本身发布在GitHub上,以查明为什么有时mysqli_query会返回null
查询本身似乎不是问题:我以两种不同的方式测试了相关SQL查询:
- 在MySQL服务器中手动执行。它们能够正确工作。 - 通过我创建的一个专门用于测试查询的脚本使用mysqli_query()。在这个测试中它们能够正常工作,并返回true
然而,在某些条件下,这些相同的查询会返回null。当mysqli_query函数开始运行时,mysqli链接对象存在,但发生了"返回null失败"。

因此,查看 PHP 的 GitHub 存储库时,我找到了名为 mysqli_nonapi.c 的文件,并在其中的第556行找到了似乎是内置的 mysqli_query 定义。查看代码后,它似乎执行了基本检查,如果失败,则返回 null。以下是上述链接的前几行:

/* {{{ proto mixed mysqli_query(object link, string query [,int resultmode]) */
PHP_FUNCTION(mysqli_query){ 
    MY_MYSQL           *mysql;
    zval               *mysql_link;
    MYSQLI_RESOURCE    *mysqli_resource;
    MYSQL_RES          *result = NULL;
    char               *query = NULL;
    size_t              query_len;
    zend_long           resultmode = MYSQLI_STORE_RESULT;
    if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
        return;
    }
    // [...]
}

尽管我有时使用C语言编写代码,但是我只了解C的一点皮毛。我知道它使用指针,我猜那些以*开头的参数就是指针。无论如何,我不确定如何解释这段代码,或者弄清楚它的内部流程如何影响PHP执行。
长话短说:我可以假设,在函数中上面显示的初始检查由于某种原因失败了。但是,要找出原因,首先需要理解那段代码。
恐怕我不能将问题隔离出来以在生产环境之外触发错误,这对详尽测试非常有用。那么,我还有什么选择?是否有办法调试该内部代码片段,或者以其他方式弄清楚它为什么可能会失败?
我在PHP5和PHP7中进行了测试;两者都失败了。

2
当然了,Zend文档仍然像垃圾一样,所以如果你要查找有关zend_parse_method_parameters()的信息,祝你好运... - Ignacio Vazquez-Abrams
1个回答

1
这在PHP中被称为未定义行为。在PHP 8中,大多数这种情况已经被消除,但是在该版本之前,如果向内置函数传递了错误的参数,该函数通常会抛出警告并返回null(或false)。
有很多情况根本不会产生任何警告!由于这是“未定义行为”,因此每个页面都没有记录此行为。
这意味着像以下代码一样的代码不会引发任何警告,只会返回null:
//                                          V - string passed instead of a numerical value
var_dump(mysqli_query($mysqli, 'SELECT 1', 'foo'));

PHP在参数类型方面非常宽容,当你传递错误的类型时,它会尝试将其转换为正确的类型,但当这不可能时,PHP没有定义应该发生什么行为。值得庆幸的是,在PHP 8.0中已经解决了99%的情况。


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