我有一个问题很长时间都无法解决。我有一个像这样的简单数据库类
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/