如何优雅地管理Kohana/PHP中的DB事务



我是Kohana的新手,但来自Spring/Java背景。

在Spring中,我习惯了所有的服务方法都自动应用DB事务。我只是标记该方法以指示它是只需要读事务还是读/写。

在科哈纳,人们在这方面做了什么?我正在使用的一个新应用程序没有交易,除非在一些他们知道有必要的地方手动进行。对我来说,这似乎有点冒险,很容易忽略一些事务一致性要求,在Spring中全局强制执行这一要求总是很好的。

在Kohana事务需要手动完成的情况下,没有办法像Spring那样完成
下面你可以找到一些处理方法:
使用Database方法:

$db = Database::instance();
$db->begin();
try
{
    // do your stuff here
    $db->commit();
}
catch(Database_Exception $e)
{
    $db->rollback();
}

使用查询生成器:

DB::query('START TRANSACTION');
// do your stuff here
If (no errors)
    DB::query('COMMIT');
else
    DB::query('ROLLBACK');

我创建了一个Kohana模块(灵感来自Spring),它使使用事务变得更加容易:

https://github.com/brazzy/kohana-transactional

添加模块后,您只需添加

public $_transactional = true;

到控制器,所有操作都会在事务中自动执行,当操作因异常而失败时,事务会回滚。在我看来,这是最有用的实现,因为在PHP项目中,拥有单独的服务层似乎并不常见。

我可能最终实现对只读事务的支持(如果可以以独立于供应商的方式实现的话)。

以下是我如何处理它:

  1. 为所有服务方法类创建一个基类:

    abstract class Base
    {
        public function __call($method,$arguments)
        {
                // Start transaction here
                echo 'start';
                try
                {                    
                    call_user_func_array(array($this, $method), $arguments);
                    // Commit
                    echo ' commit';
                }
                catch ($e)
                {
                    // Roll back
                }                       
        }
    }
    
  2. 创建一个具有所有"受保护"功能的子类:

    class Member extends Base
    {
            protected function test()
            {
                echo 'test';
            }
    }
    
  3. 呼叫服务方式:

    $member = new Member();
    $member->test();
    

它将显示:"开始测试提交"

这里的技巧是,你必须对所有函数使用"protected",否则它将不再运行(它将直接调用"test"函数,而不是通过__call()。

手工完成并针对您的个人情况:

$db = Database::instance();
$db->begin();
try{
    // do your stuff
    $db->commit();
}catch(ORM_Validation_Exception $e){
    // ceep care WHAT you catch
    $db->rollback();
}catch(Exception $e){
    // and catch whatever exceptions too
    // or your rollback is blown in the wind
    $db->rollback();
    throw $e;
}

最新更新