我是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项目中,拥有单独的服务层似乎并不常见。
我可能最终实现对只读事务的支持(如果可以以独立于供应商的方式实现的话)。
以下是我如何处理它:
-
为所有服务方法类创建一个基类:
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 } } }
-
创建一个具有所有"受保护"功能的子类:
class Member extends Base { protected function test() { echo 'test'; } }
-
呼叫服务方式:
$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;
}