Как элегантно управлять транзакциями с БД в Kohana / PHP - PullRequest
2 голосов
/ 13 февраля 2012

Я новичок в Kohana, но пришел из Spring / Java.

Весной я привык ко всем методам обслуживания, к которым автоматически применяются транзакции с БД. Я просто помечаю метод, чтобы указать, нужна ли ему только транзакция чтения или чтения / записи.

Что люди делают по этому поводу в Кохане? В новом приложении, с которым я работаю, нет транзакций, кроме как вручную, в нескольких местах, где они знают, что это необходимо. Мне это кажется немного рискованным, легко пропустить некоторые требования к транзакционной согласованности, всегда было приятно иметь глобальное применение в Spring.

Ответы [ 4 ]

4 голосов
/ 13 февраля 2012

В Kohana транзакции должны выполняться вручную, нет способа сделать это, как в Spring.
Ниже вы можете найти несколько способов, как с этим справиться:
Использование Database методов:

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

try
{
    // do your stuff here

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

Использование Query Builder:

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

If (no errors)
    DB::query('COMMIT');
else
    DB::query('ROLLBACK');
2 голосов
/ 08 апреля 2012

Я создал модуль Kohana (вдохновленный Spring), который значительно упрощает использование транзакций:

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

После добавления модуля вы можете просто добавить

public $_transactional = true;

к контроллеру, и все действия автоматически выполняются внутри транзакции, которая откатывается, когда действие завершается неудачей с исключением.Мне показалось, что это наиболее полезная реализация, так как наличие отдельного сервисного уровня, по-видимому, не распространено в проектах PHP.

Я могу в конечном итоге реализовать поддержку транзакций только для чтения (если это возможно сделатьнезависимым от поставщика способом).

1 голос
/ 15 декабря 2013

Сделайте это вручную и для ваших индивидуальных ситуаций:

$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;
}
1 голос
/ 29 февраля 2012

Вот как я с этим справляюсь:

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

Будет отображено: «начать тестовый коммит»

Хитрость в том, что вам придется использовать «защищенный» для всех ваших функций, в противном случае он больше не будет работать (он будет вызывать функцию «тест» напрямую, а не через __call ().

...