我正在使用PHP Active Record开发一个项目并且是新手,我真的开始喜欢它了。所有对象都是ActiveRecord模型的扩展
class User extends Model {
}
class Item extends Model {
}
.
.
.
现在我的代码将有类似的内容(users表包含属于用户的项目的计数,items表包含项目)。
$user = User::find_by_id($id);
$user->num_items++;
$item = new Item();
//Do stuff with the item
$user->save();
$item->save();
现在我担心理论上的机会,当网站遭受重创或者数据库被拆除进行维护时(是的,这些事情与我有关)。由于这些陈述理论上不在交易中:
$user->save();
//User table is updated successfully
//----- MySQL goes Down Here -------/
$item->save(); //This won't run, now the user's table may say he has 4 items but he only has 3 since the last one didn't get inserted
我希望能够将用户和项目保存在一起,如果一方失败则会回滚。我知道如何在手动MySQL中执行此操作,但这违背了使用ORM的目的。
答案 0 :(得分:3)
对于仍在使用此库的人来说,它可能会有用。 每个模型都有交易方法
$user = User::find_by_id($id);
$item = new Item();
$entity::transaction(function() use ($user, $item) {
//Do stuff with the items...
$user->name = 'somename';
$user->save();
$item->quantity = 0;
$item->save();
});
它位于\ ActiveRecord \ Model命名空间(它是项目模型的父类)
您可以使用此公共静态方法使用闭包运行事务查询。 例如:
\ActiveRecord\Config::initialize(function ($cfg) use ($hostname, $username, $password, $database, $port) {
$cfg->set_model_directory('/src/Entity');
$cfg->set_connections(
array(
'development' => 'mysql://' . $username . ':' . $password . '@' . $hostname . '/' . $database
)
);
});
以上事务静态方法使用模型中的连接实例,如果每个模型具有相同的连接,则不会有任何问题。例如,我的所有模型只有一个连接
YourModel::transaction(function()
{
YourModel::create(array("name" => "blah"));
throw new Exception("rollback!");
});
YourModel::transaction(function()
{
YourModel::create(array("name" => "blah"));
return false; # rollback!
});
如果你有一些内部验证等,你可以抛出\ Exception或从你的闭包中返回false并且事务将被回滚
$user = User::find_by_id($id);
$item = new Item();
$connection = ConnectionManager::get_connection();
$connection->transaction();
try{
//Do stuff with the items...
$user->name = 'somename';
$user->save();
$item->quantity = 0;
$item->save();
$connection->commit();
}
catch (\Exception $exception){
throw $exception;
$connection->rollback();
}
您也可以像往常一样获取连接实例并开始交易
{{1}}
ps:这里还有一些例子http://www.phpactiverecord.org/docs/ActiveRecord/Model#methodtransaction
答案 1 :(得分:0)
在save()函数实现mysql_query的情况下,这种代码应该可以解决问题。 由您自己将其封装在一个漂亮的界面中,以便那些丑陋的mysql_querys也由您的活动记录框架处理
mysql_query("SET AUTOCOMMIT=0");
mysql_query("START TRANSACTION");
$a1=$user->save();
$a2=$item->save();
if ($a1 and $a2) {
mysql_query("COMMIT");
} else {
mysql_query("ROLLBACK");
}