Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/233.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以用PHP检测和处理MySQL警告吗?_Php_Mysql_Error Handling_Warnings - Fatal编程技术网

我可以用PHP检测和处理MySQL警告吗?

我可以用PHP检测和处理MySQL警告吗?,php,mysql,error-handling,warnings,Php,Mysql,Error Handling,Warnings,我正在处理一个MySQL表,它将JobName列定义为唯一的。如果有人试图使用数据库中已有的作业名将新作业保存到数据库中,MySQL将抛出警告 我希望能够在我的PHP脚本中检测到这个警告,就像一个错误一样,并适当地处理它。理想情况下,我想知道MySQL抛出了什么样的警告,这样我就可以对代码进行分支来处理它 这可能吗?如果没有,是因为MySQL没有这个功能,PHP没有这个功能,还是两者都没有?首先,您应该让访问者不会看到您的MySQL错误。第二,当你打电话时,你应该检查它是否返回false。如果有

我正在处理一个MySQL表,它将JobName列定义为唯一的。如果有人试图使用数据库中已有的作业名将新作业保存到数据库中,MySQL将抛出警告

我希望能够在我的PHP脚本中检测到这个警告,就像一个错误一样,并适当地处理它。理想情况下,我想知道MySQL抛出了什么样的警告,这样我就可以对代码进行分支来处理它

这可能吗?如果没有,是因为MySQL没有这个功能,PHP没有这个功能,还是两者都没有?

首先,您应该让访问者不会看到您的MySQL错误。第二,当你打电话时,你应该检查它是否返回false。如果有,打电话找出哪里出了问题。将返回的数字与上的错误代码匹配

看起来这是您要查找的错误号:

错误:1169 SQLSTATE:23000(ER_DUP_UNIQUE)

消息:由于唯一约束,无法写入表“%s”


更新以删除关于errno函数的内容,我现在意识到这些函数不适用于您的情况

在MySQL中,对于
UPDATE
语句需要注意的一件事是:
mysqli\u infected\u rows()
将返回零,即使
WHERE
子句匹配行,但
SET
子句实际上并没有更改数据值。我之所以提到这一点,是因为在我曾经看过的一个系统中,这种行为导致了一个bug——程序员在更新后使用该返回值检查错误,假设零意味着发生了一些错误。这只是意味着用户在单击更新按钮之前没有更改任何现有值

因此,我想使用
mysqli\u impacted\u rows()
也无法找到此类警告,除非您的表中有一个类似于
update\u time
的列,在更新时该列将始终被分配一个新的时间戳值。不过,这种解决方法似乎有点困难。

根据您使用的框架(如果有的话),我建议您自己进行查询以检查jobname,并创建适当的信息供用户使用,以及表单的其余验证

根据作业名称的数量,您可以将名称发送到包含表单的视图,并使用javascript告知所使用的名称

如果这对你来说没有意义,那么总结一下我的观点就是:不要设计你的程序和/或用户试图做非法的事情,在他们做的时候抓住错误,然后处理它。imho,将系统设计为不产生错误要好得多。将错误保留在实际的bug中:)

对于以本机方式“标记”到PHP的警告,需要更改mysql/mysqli驱动程序,这显然超出了本问题的范围。相反,您必须基本上检查您在数据库上进行的每个查询是否存在警告:

$warningCountResult = mysql_query("SELECT @@warning_count");
if ($warningCountResult) {
    $warningCount = mysql_fetch_row($warningCountResult );
    if ($warningCount[0] > 0) {
        //Have warnings
        $warningDetailResult = mysql_query("SHOW WARNINGS");
        if ($warningDetailResult ) {
            while ($warning = mysql_fetch_assoc($warningDetailResult) {
                //Process it
            }
        }
    }//Else no warnings
}
显然,大规模应用这项技术的成本将非常高昂,因此您可能需要仔细考虑何时以及如何出现警告(这可能会导致您进行重构以消除警告)

作为参考


当然,您可以省去对
SELECT@@warning\u count
的初始查询,这将在每次执行时为您保存一个查询,但为了学究式的完整性,我将其包括在内。

您可以使用mysqli语句错误号检测唯一的密钥冲突。mysqli语句返回错误1062,即ER\u DUP\u条目。您可以查找错误1062并打印适当的错误消息。如果您想打印列(jobName)作为错误消息的一部分,那么您应该解析语句错误字符串

if($stmt = $mysqli->prepare($sql)){ $stmt->bind_param("sss", $name, $identKey, $domain); $stmt->execute(); if($mysqli->affected_rows != 1) { //This will return errorno 1062 trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR); exit(1); } $stmt->close(); } else { trigger_error('mysql error >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR); } 如果($stmt=$mysqli->prepare($sql)){ $stmt->bind_参数(“sss”, $name, $identKey, $domain); $stmt->execute(); 如果($mysqli->受影响的行!=1){ //这将返回错误号1062 触发错误('mysql错误>>'。$stmt->errno'::'。$stmt->error,E_USER_error); 出口(1); } $stmt->close(); }否则{ 触发_错误('mysql错误>>'。$mysqli->errno'::'。$mysqli->错误,E_用户_错误); }
使用mysqli比使用mysql更有效地获取警告是可能的

以下是php.net手册中建议的属性mysqli->warning\u count的代码:

$mysqli->query($query);

if ($mysqli->warning_count) {
    if ($result = $mysqli->query("SHOW WARNINGS")) {
        $row = $result->fetch_row();
        printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
        $result->close();
    }
}

关于禁止显示警告的注意事项:一般来说,防止显示警告不是一个好主意,因为您可能遗漏了一些重要的内容。如果出于某种原因必须隐藏警告,您可以在语句前面单独放置一个
@
符号。这样,您就不必关闭所有警告报告,并且可以将其限制到特定实例

例如:

 // this suppresses warnings that might result if there is no field titled "field" in the result
 $field_value = @mysql_result($result, 0, "field");
可能就是你要找的


然后可以使用自定义PHP错误处理程序处理PHP错误,但您也可以关闭显示PHP错误,因为它们通常会记录到日志文件中(取决于您的PHP配置)。

或者使用具有警告计数属性的MySQLi驱动程序。听起来用户希望能够捕捉到错误,而不是阻止它。最好使用
ini\u集('display\u errors',0)(更好的是,把它放在php.ini中),这样用户就不会看到任何可能带来安全风险的东西。除此之外,我还建议确保将
error\u log
设置为可写文件,并将
error\u reporting=-1
设置为可写文件,以便了解所有潜在问题。如果我没弄错的话,他问的是警告,而不是错误。警告仍然允许查询通过,因此
mysql\u query
不会返回
false
。有关PHP有限的警告支持,请参见iAn的回答。
ini_set('mysql.trace_mode', 1)