使用mysqli处理错误


Error handling with mysqli

我正在折射一些旧代码,并使用INSERT函数创建一个数据库类。为了测试的目的,我把它放在了类之外,并希望让它处理错误。

我想删除php错误并返回我自己的错误。目前,我有以下内容,可以在重复键上插入,但当我测试从bind_param中删除类型参数时,我会收到以下错误:

警告:mysqli_stmt::bind_param():在第17行的/home/matt500b/csgoberry/public/catch.php中指定的类型无效或没有指定类型

执行语句失败:没有为准备好的语句中的参数提供数据

如何删除"警告"问题并只保留返回的字符串?或者,对于生产服务器来说,执行这种操作的最佳方法是什么。

另外,对于mysqli查询,我还可以模拟哪些其他错误?

function INSERT($link, $sql, $args=null) {
    
    if ($stmt = $link->prepare($sql)) {
        for($i=0; $i<count($args); $i++) {
            $stmt->bind_param($args[$i]["type"], $args[$i]["value"]); 
        }
        if(!$stmt->execute()) {
            return 'Executing the statement failed: ' . htmlspecialchars($stmt->error);
            exit();
        }
    }
    else {
        return 'Preparing the statement failed: ' . htmlspecialchars($link->error);
        exit();
    }
    
    return 'Finished';
}
$query = "INSERT INTO insertTest (`value`) VALUES (?)";
$queryArgs[] = array("type"=>"", "value"=>"test1");
echo INSERT($link, $query, $queryArgs);

坦率地说,错误处理的整个想法是错误的。返回错误消息的函数是致命的罪过。函数应该返回与其目的相关的内容。例如,插入函数应该返回一个语句,以允许您使用其中的affected_rows变量。

而错误必须以完全不同的方式处理。

此外,您使用mysqli的方式是错误的,而且这些代码无论如何都不会工作。

假设您是出于某种原因进行重构的,并且可以使用已经稍微过时的PHP 5.6版本,下面是运行ANY查询的函数,而不仅仅是INSERT:

function query($link, $query, $params = NULL, $types = NULL)
{
    if (!$params)
    {
        return $link->query($query);
    }
    $statement = $link->prepare($select);
    $types = $types ?: str_repeat('s', count($params));
    $statement->bind_param($types, ...$params);
    $statement->execute();
    return $statement;
}

这就是的使用方法

$query = "INSERT INTO insertTest (`value`) VALUES (?)";
query($link, $query, ['test1']);

或者,如果你想设置类型,

$query = "INSERT INTO insertTest (`value`) VALUES (?)";
query($link, $query, ['test1'], "s");

现在,我们来谈谈错误报告这一令人兴奋的话题。按照这个答案中解释的去做。

简而言之:mysqli已经可以报告错误了,而且可以比代码做得更好。所以,别管它,让PHP处理所有错误。

如果您想禁止警告,您可以将@operator放在引起警告的函数或方法调用前面:

@$stmt->bind_param($args[$i]["type"], $args[$i]["value"]);

不过,通常情况下,在将数据传递给较低级别的函数之前,您应该检查传递到函数中的无效数据,这意味着不需要@,因为在错误情况下不会调用较低级别函数。