我有一个问题,我很长时间都无法解决。我有一个像这样的简单DB类
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;
}
一个Service Class,带有在DB中写入数据的方法。表的类型是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));
?>
db.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;
}
}
?>
答案 0 :(得分:1)
将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;
}
并且在关闭它之前将为使用此连接的所有内容设置它。
现在您可以将其从您设置的任何其他地方删除
注:
也许这只是对何时抛出异常的误解。
当PDO :: ATTR_ERRMODE设置为PDO :: ERRMODE_EXCEPTION时,将抛出异常。
BUT:
如果
PDO::ATTR_EMULATE_PREPARES = fale
->prepare()
语句向数据库发出查询以进行编译,那么如果查询无法编译,您将获得->prepare()
抛出的异常。现在,如果
PDO::ATTR_EMULATE_PREPARES = true
准备语句很少。此时不会向数据库发出查询以进行编译。查询将作为->execute()
处理的一部分发送到数据库进行编译,并且` - &gt; execute()语句将抛出与编译失败相关的任何异常抛出。
答案 1 :(得分:0)
看起来你的其他一些代码正在将PDO :: ERRMODE_EXCEPTION设置为另一个值。
如果您懒得编写一个隔离工作示例,其中包含仅您在此处发布的代码,您将看到该异常将被抛出。