php - 使用模型时如何在 PHP Active Record 中创建事务?

标签 php mysql activerecord transactions

我正在使用 PHP Active Record 开发一个项目,我是新手,但我真的开始喜欢上它了。所有的对象都是 ActiveRecord 模型的扩展

class User extends Model {

}

class Item extends Model {

}
.
.
.

现在我的代码将包含与此类似的内容(用户表包含属于用户的项目计数,项目表包含项目)。

    $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 的目的。

最佳答案

也许它对仍在使用这个库的人有用。 您的每个模型中都有交易方法

public static function transaction($closure)

它位于\ActiveRecord\Model 命名空间(它是您的项目模型的父类)

您可以使用此公共(public)静态方法通过闭包运行您的交易查询。 示例:

$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\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
                )
            );
        });

如果你有一些内部验证等你可以抛出\Exception 或从你的闭包中返回 false 并且事务将被回滚

  YourModel::transaction(function()
      {
        YourModel::create(array("name" => "blah"));
        throw new Exception("rollback!");
      });

      YourModel::transaction(function()
      {
        YourModel::create(array("name" => "blah"));
        return false; # rollback!
      });

您还可以像往常一样获取连接实例并开始您的交易

  $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();
   }

ps:这里也有一些例子http://www.phpactiverecord.org/docs/ActiveRecord/Model#methodtransaction

关于php - 使用模型时如何在 PHP Active Record 中创建事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24679392/

相关文章:

mysql - Symfony2 和 Doctrine Mysql 测试数据库 Persist

ruby-on-rails - 如何删除和返回 ActiveRecord 关系对象中的第一个元素?

ruby-on-rails - 在已存在的集合中添加对象时引发异常

php - 是否有免费且良好的 PHP 行级分析器?

JavaScript JSON 关联对象键和值都作为日期时间戳

php - cpanel升级到mariadb后我无法连接到数据库

sql-server - 为什么我会遇到 SQL Server ActiveRecord 适配器的段错误?

php - 用于从数组中 checkin 字符串的八进制

php - laravel 4 创建模块并将 Controller 、模块和 View 放入模块中

mysql - 如何优化count by max的主从查询?