Как поместить транзакцию begin-commit в контроллер: cakephp? - PullRequest
4 голосов
/ 23 сентября 2011

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

Вот мой образец:

Контроллер:

//update table when update button is clicked
    if (!empty($this->data)) {
        if ($this->Item->update($this->data)) {
            $this->Item->create();
            $this->redirect('/sample');
            return;
        } else {
            $this->set('data', $this->data);
        }
    }

Модель:

function update($data)
{
    $this->begin($this);
    if(!parent::save($data)) {
        $this->rollback($this);
        return false;
    }

    $this->commit();
    return true;
}

Теперь это работает нормально. Но мне нужно вызвать другую модель в моем контроллере, например, «$ this ->« ANOTHER MODEL HERE »-> update ()». Мне нужно сделать откат, если возникнет проблема с любой моделью транзакции. Я думаю о том, чтобы поместить коммит в мой контроллер после успешного вызова обеих моделей.

Примерно так:

CONTROLLER PHP:
  BEGIN TRANSACTION
    ->CALLS MODEL1
        IF(MODEL1 == ERROR){
             ROLLBACK
        }
    ->CALLS MODEL2
        IF(MODEL2 == ERROR){
             ROLLBACK
        }
   COMMIT WHEN NO PROBLEM IS ENCOUNTERED

Так можно ли выполнить коммит в контроллере? Я могу сделать это только в модели. Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 21 июня 2013

Так возможно ли выполнить коммит в контроллере?Я могу сделать это только в модели.

Да, вы можете выполнить коммит или откат из контроллера.Вы должны сначала получить источник данных от одной из ваших моделей.В коде контроллера просто укажите одну из используемых вами моделей (при условии, что все они находятся в одной базе данных):

$ds = $this->MyModelName->getdatasource();

Затем вы можете начать, зафиксировать и выполнить откат к этому источнику данных из контроллера.

$ds->begin();

// do stuff and save data to models

if($success)
{
    $ds->commit();
}
else
{
    $ds->rollback();
}

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

Обработка транзакций в контроллере имеет для меня наиболее смысл, поскольку действие контроллера - это то, где границы транзакций действительно находятся концептуально.Идея транзакции естественным образом охватывает обновления для нескольких моделей.Я делал это, используя postgres в качестве внутренней базы данных с Cake 2.2 и 2.3, и здесь все работает отлично.YMMV с другими двигателями БД, хотя я подозреваю.

0 голосов
/ 05 ноября 2013

Я использовал commit в моих операторах if и откат в моих инструкциях else.Поскольку я использовал две разные модели внутри контроллера, я создал два разных источника данных

        $transactiondatasource = $this->Transaction->getDataSource();
        $creditcarddatasource = $this->Creditcard->getDataSource();
        $transactiondatasource->begin();
        $creditcarddatasource->begin();

        if (CONDITION){
                $creditcarddatasource->commit();
                $transactiondatasource->commit();
                CakeSession::delete('Cart');
            } else {
                $this->Session->setFlash(__('MESSAGE'));
                $creditcarddatasource->rollback();
                $transactiondatasource->rollback();
            }   
0 голосов
/ 24 октября 2011

Сделки должны быть улучшены в фьючерсных версиях CakePHP, как вы можете видеть в этом билете на CakePHP Lighthouse .

Здесь предлагается два возможных решения, и я показываю вамтретий.Вы можете создать собственный метод для его сохранения и зафиксировать транзакции вручную:

public function saveAndUpdate($data) {
    $ds = $this->getDataSource();
    $ds->begin();
    if ($this->save($data)) {
        foreach(Array('Model1', 'Model2') as $model) {
            if (!ClassRegistry::init($model)->update()) {
                $db->rollback();
                return false;
             }
         }
         return $db->commit() !== false;
     }
     return false;
 }

Я написал этот код, чтобы проиллюстрировать, как я думаю о вашей проблеме, хотя я не тестировал.

Дополнительные полезные ссылки:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...