Question

I'm new to Kohana but come from a Spring/Java background.

In Spring I'm used to all service methods automatically having DB transactions applied to them. I just tag the method to indicate whether it only needs a read transaction or read/write.

What do people do in this regard in Kohana? A new app I'm working with doesn't have transactions except manually in a few places where they know it's necessary. To me this seems a bit risky, it's easy to overlook some transactional consistency requirement, it was always nice to have that globally enforced in Spring.

Was it helpful?

Solution

Here is how I deal with it:

  1. Create a base class for all service method classes:

    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. Create a child class with all "protected" functions:

    class Member extends Base
    {
            protected function test()
            {
                echo 'test';
            }
    }
    
  3. Call service method:

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

It will display: "start test commit"

The trick here is you will have to use "protected" for all your functions, if not it will no longer run (it will call the "test" function directly, not through __call().

OTHER TIPS

In Kohana transactions need to be done manually, there is no way to do it like in Spring.
Below you can find some ways how to deal with it:
Using Database methods:

$db = Database::instance();
$db->begin();

try
{
    // do your stuff here

    $db->commit();
}
catch(Database_Exception $e)
{
    $db->rollback();
}

Using Query Builder:

DB::query('START TRANSACTION');
// do your stuff here

If (no errors)
    DB::query('COMMIT');
else
    DB::query('ROLLBACK');

I've created a Kohana module (inspired by Spring) that makes using transactions a lot easier:

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

After adding the module, you can just add

public $_transactional = true;

to the controller, and all actions are automatically executed inside a transaction, which is rolled back when the action fails with an exception. This seemed to me to be the most useful implementation, as having a separate service layer doesn't seem to be common in PHP projects.

I may eventually implement support for read-only transactions (if it's possible to do in a vendor-independant way).

Do it by Hand and for your individual situations:

$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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top