PHP PDO 异常

标签 php mysql exception pdo transactions


我有一个问题很长时间都无法解决。我有一个像这样的简单数据库类

class DB {

    private static $dbserver = "mysql:dbname=db;host=localhost";
    private static $dbuser = "root";
    private static $dbpass = "";

    public static function connectDB() {

        @$dbh = new PDO(self::$dbserver, self::$dbuser, self::$dbpass);
        $dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
        $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8');

        return $dbh;
    }

以及一个具有在数据库中写入数据的方法的服务类。表的类型是InnoDB。服务类如下所示

function insert_data($data) {
    $error = NULL;
    try {
        $dbh = DB::connectDB();
        $dbh->beginTransaction();

        $query_insert_1 = 'INSERT INTO table (f1, f2, f3) VALUES (?,?,?)';
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $stmt = $dbh->prepare($query_insert_1);
        $stmt->execute(array($d1, $d2, $d3));

        $last_insert_id = $dbh->lastInsertId();

        $query_insert_2 = 'INSERT INTO table2 (f4, f5, f6) VALUES (?,?,?)';
        $stmt = $dbh->prepare($query_insert_2);
        $stmt->execute(array($last_insert_id, $d4, $d5));

        $dbh->commit();             
    }
    catch(Exception $e) {                       
        $dbh->rollback();
        $error = $e->getMessage();
    }
    $return = new Result($error ? 1 : 0, $error ? 0 : 1, $error ? $error : '', NULL);
    error_log(print_r($error,1));
    return $return;
}

如果我在函数 insert_data 中将 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_EXCEPTION,PDO 只会引发异常。如果我在 DB 类中设置它,则不会抛出异常。这种行为的原因是什么?

当我在这个问题的函数中设置常量时,我​​有抛出异常的解决方案( PDO exception is not being thrown )

感谢帮助

迈克尔

编辑: 我原来的代码如下

class CarService {

private $dbh;

function __construct($dbh) {
    $this->dbh = $dbh;
}

function insert_car($customer_id, $brand, $model) {
    $error = NULL;

    try {
        $this->dbh->beginTransaction();

        $query_insert_car = 'INSERT INTO fahrzeug (kunde_id, fabrikat, modell) VALUES (?,?,?)';

        $stmt = $this->dbh->prepare($query_insert_car);
        $stmt->execute(array($customer_id, $brand, $model));
        // Get the ID of the last inserted car
        $last_insert_id = $this->dbh->lastInsertId();
        // Create the entry of the corresponding car version
        $query_insert_car_version = 'INSERT INTO fahrzeugversion (fahrzeug_id, version, fabrikat, modell) VALUES (?,?,?,?)';
        $stmt = $this->dbh->prepare($query_insert_car_version);
        $stmt->execute(array($last_insert_id, 1, $brand, $model));

        $this->dbh->commit();               
    }
    catch(Exception $e) {                       
        $this->dbh->rollback();
        $error = $e->getMessage();
    }

    $return = new Result(1, 0, NULL, NULL);
error_log(print_r($error,1));
    return $return;
}

new_car.php

<?php

require_once('DB.php');
require_once('CarService.php');
require_once('Result.php');

$dbh = DB::connectDB();
$car_service = new CarService($dbh);

$result = new Result(1, 0, NULL, NULL);

if (isset($_POST['fabrikat']) && isset($_POST['modell'])) {
    $brand = trim($_POST['fabrikat']);
    $model = trim($_POST['modell']);

    $result = $car_service->insert_car(1, $brand, $model);          
}   
print_r(json_encode($result));
?>

数据库.php

<?php

class DB {

    private static $dbserver = "mysql:dbname=db;host=localhost";
    private static $dbuser = "root";
    private static $dbpass = "";

    public static function connectDB() {

        $dbh = new PDO(self::$dbserver, self::$dbuser, self::$dbpass);
        $dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
        $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8');
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $dbh;
    }

}
?>

最佳答案

PDO::ERRMODE_EXCEPTION 属性添加到 PDO 连接过程

public static function connectDB() {

    $dbh = new PDO(self::$dbserver, self::$dbuser, self::$dbpass);
    $dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
    $dbh->setAttribute(\PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8');
    $dbh->setAttribute(\PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    return $dbh;
}

并且它将为使用此连接的所有内容进行设置,直到您关闭它。

现在您可以将其从您设置的其他任何地方删除

NOTE:

Maybe this is just a misunderstanding about when the exception will be thrown.

When PDO::ATTR_ERRMODE is set to PDO::ERRMODE_EXCEPTION exceptions will be thrown.

BUT:

If PDO::ATTR_EMULATE_PREPARES = fale the ->prepare() statement issues the query to the database for compilation, therefore you will get the exception thrown by the ->prepare() if the query does not compile.

Now if PDO::ATTR_EMULATE_PREPARES = true the prepare statement does very little. The query is not issued to the database for compilation at this point. The query will be issued to the database for compilation as part of the ->execute() processing and any execptions thrown relating to failed compilation will be thrown by the `->execute() statement.

关于PHP PDO 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41728870/

相关文章:

php - Paypal IPN 脚本 : create a php on my site that receives confirmed payment messages and inserts into wordpress db

php - Apache 子进程以状态 255 退出

php - mysqli 数据库连接类不工作

mysql - SQL游标和存储过程顺序排列

Mysql select语句包含where子句所以不适合插入

php - 在 xmlhttprequest 加载的页面中运行 javascript

java - 使用可序列化传递对象时出错?

java - 如何使用 ldap 对用户进行身份验证,同时忽略 NameNotFoundException?

c++ - g++ 6.2 的不同异常说明符

php - 查找给定 IP 是否存在于 CIDR 中