我可以让PHP's PDO返回MySQL警告,而不仅仅是错误消息


Can I get PHP's PDO to return MySQL warnings, instead of only error messages?

我正在尝试向用户返回尽可能多的信息,并且我希望能够告诉他们他们刚刚执行的某个操作是否有警告,例如,如果数据由于被塞进太短的字段而被截断,或者他们试图将字母或小数放入整数字段中。

为了测试的目的,我在一个单独的页面上减少了我的代码:

<?php
        error_reporting(E_ALL);
        ini_set('display_errors', True);
        session_start();
        include '../php/security.php';
        sec::dieifnotvalid();
        include '../php/db_connection_params.php';
        $pdo_conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
        $qry_string = "insert into tbl_engine (capacity) values (?)";
        $var_array = array('gfd');
        $q = $pdo_conn->prepare($qry_string);
        $q->execute($var_array);
        $return_arr = $q->fetchAll();

        var_dump($q->errorInfo());
        ?>

如果我尝试执行这样的操作,

$qry_string = "insert into tbl_manufacturer_lookup (manufacturer_name) values (?)";
$var_array = array('Audi');

将一个重复条目插入到唯一列中,我得到

array(3) { [0]=> string(5) "00000" [1]=> int(1062) [2]=> string(57) "Duplicate entry 'Audi' for key 'manufacturer_name_UNIQUE'" }

打印在页面上。这很好。

但是如果我这样做,

    $qry_string = "insert into tbl_engine (capacity) values (?)";
    $var_array = array('hjgt');

向整数字段插入字符串时,errorinfo为

array(3) { [0]=> string(5) "HY000" [1]=> NULL [2]=> NULL }

,这与插入整数值完全相同。

通过比较,MySQL工作台将返回如下内容:
1 row(s) affected, 1 warning(s): 1366 Incorrect integer value: 'fdd' for column 'capacity' at row 1

我真的想让我的web应用程序返回一些有用的东西像这样

执行SHOW WARNINGS查询。

对于那些正在寻找的人来说,一个快速而简单的方法是使用查询SHOW WARNINGS。这是一个可以根据需要重用的简单函数。

function lastWarning($pdo)
{
    var_dump($pdo->query("SHOW WARNINGS")->fetch());
}

你可以把它做得尽可能漂亮。例如,在PDO子类中:

namespace Foo;
class PDO extends 'PDO 
{
    public function getWarning()
    {
        $warnings = $this->query('SHOW WARNINGS')->fetch();
        if ($warning['Level'] == 'Error') {
            return "Warning: {$warning['Message']} [#{$warning['Code']}]'n";
        }
    }
}

如果我是你,我就不会依赖这样的警告。在PHP中,您应该简单地执行额外的查询和验证数据,并显示一些警告(例如,对于重复的唯一键)或应该是整数的字段(但它们不是)。

否则,你可能会在数据库中插入一些不应该放在那里的数据(例如,5,52作为小数会有问题,也许你应该在PHP中纠正它,或者让用户输入正确的值)

要提取PDO警告,请像这样初始化PDO对象:

$pdo_conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass, array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING
));

注意,这只能用于调试目的,因为消息通常包含敏感信息。

相关文章: