我有一个Model类,它在Model.php中,我有两个模型,比如ModelOne.php和ModelTwo.php中的ModelOne和ModelTwo。这些模型扩展了基础Model类。模型类扩展了一个DatabaseConnector类,它使用PDO与数据库进行交互。
class ModelOne extends Model {
public function storeX($params1) {
$query = 'insert ...';
return $this->insert($query, $params1);
}
}
class ModelTwo extends Model {
public function storeY($params2) {
$query = 'insert ...';
return $this->insert($query, $params2);
}
}
class Model extends DatabaseConnector {/* not related to this question */}
class DatabaseConnector {
private $_mysql;
public function __construct() {
$this->_mysql = new PDO(...);
}
public function insert($query, $params = array()) {
$sql_stmt = $this->_mysql->prepare($query);
foreach($params as $i => $param) {
$sql_stmt->bindValue(++$i, $param['value'], $param['type']);
}
$sql_stmt->execute();
return $this->_mysql->lastInsertId();
}
}
我在我的模型类中运行两个不同的函数,如下所示:
/* begin transaction */
$model1 = new ModelOne();
$anotherParam = $model1->storeX($params1);
$model2 = new ModelTwo();
$model2->storeY($params2, $anotherParam);
/* end transaction */
我想要这两个存储函数(每个函数从PDO运行“prepare”,“bindValue”和“execute”)作为事务运行。我该怎么办?我不想改变我的MVC结构。
编辑:
$anotherParam
变量已添加。
答案 0 :(得分:1)
DatabaseConnector
和类继承如果try...catch
和storeX()
方法在失败时返回storeY()
个对象,则可以使用几个Exception
块来安排“事务”回退:
try {
$model1 = new ModelOne();
$anotherParam = $model1->storeX($params1);
} catch (Exception ex) {
//First INSERT failed
//Handle the issue and don't continue
exit;
}
try {
$model2 = new ModelTwo();
$model2->storeY($params2, $anotherParam);
} catch (Exception ex) {
//Second INSERT failed
//Roll back the first INSERT!
$model1->removeX($anotherParam);
}
DatabaseConnector
的使用方式使用正确的MySQL数据库端事务会更好,但这需要您拥有在各种ModelX
对象之间共享的单一数据库连接。
您应该扩展DatabaseConnector
以便很好地处理交易(正如@jayxhj所建议的那样),这将满足您的需求。
如果您希望/需要所有模型使用DatabaseConnector
类的相同实例(这将允许您使用在您的ModelX
类中的事务,如果你想要的,你可以制作DatabaseConnector
工具the singleton pattern。
我认为您的ModelX
类不应该扩展DatabaseConnector
类 - 它们似乎不是数据库连接器的更具体版本。相反,我认为ModelX
类应该像这个例子那样使用DatabaseConnector
:
包含交易中的来电
//Start transaction
$db = DatabaseConnector::getInstance();
$db->beginTransaction();
try
{
//Do database work
$model1 = new ModelOne();
$anotherParam = $model1->storeX($params1);
$model2 = new ModelTwo();
$model2->storeY($params2, $anotherParam);
//Commit the whole transaction
$db->commit();
}
catch (Exception ex)
{
//Roll back the whole transaction
$db->rollback();
}
模型类
class Model {
private $_mysql;
public function __construct() {
//Get "singleton" instance of the DatabaseConnector (shared between all Models)
$this->_mysql = DatabaseConnector::getInstance();
}
}
DatabaseConnector类
class DatabaseConnector extends Singleton {
private $_mysql;
public function __construct() {
$this->_mysql = new PDO(...);
}
public function beginTransaction() {
return $this->_mysql->beginTransaction();
}
public function commit() {
return $this->_mysql->commit();
}
public function rollback() {
return $this->_mysql->rollback();
}
}
单身人士课程
class Singleton
{
/**
* @var Singleton The reference to *Singleton* instance of this class
*/
private static $instance;
/**
* Returns the *Singleton* instance of this class.
*
* @return Singleton The *Singleton* instance.
*/
public static function getInstance()
{
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Protected constructor to prevent creating a new instance of the
* *Singleton* via the `new` operator from outside of this class.
*/
protected function __construct()
{
}
/**
* Private clone method to prevent cloning of the instance of the
* *Singleton* instance.
*
* @return void
*/
private function __clone()
{
}
/**
* Private unserialize method to prevent unserializing of the *Singleton*
* instance.
*
* @return void
*/
private function __wakeup()
{
}
}
答案 1 :(得分:1)
@Nerdwood 的答案符合您的需求。
还有另一种方式
try {
$pdo = new PDO(...);
$pdo->beginTransaction();
$model1 = new ModelOne();
$anotherParam = $model1->storeX($params1);
$model2 = new ModelTwo();
$model2->storeY($params2, $anotherParam);
$pdo->commit();
}
catch (Exception $e) {
$pdo->rollback();
}
但您应修改DatabaseConnector类以提供公共数据库处理程序以支持事务。
Nerdwood的答案是将其作为语言级别的交易,我的答案是数据库处理交易本身的一种方式。
此外,如果数据库引擎支持事务,则应检查数据库引擎。