2011-08-29 2 views
3

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

Возможно ли в Cake выполнить транзакцию, содержащую запросы, охватывающие несколько моделей?

Все, что я нашел до сих пор, это DataSource::begin/commit/rollback(), но это поддерживает только запросы к одиночным моделям.

+1

Возможный дубликат http://stackoverflow.com/questions/3013347/transaction-management-with-multiple-models-using-single-transaction-commit-and-r – 8vius

+1

Ух, вы правы. Тот же фундаментальный вопрос, и, по-видимому, нет решения, судя по отсутствию соответствующего ответа. –

+0

Если вы хотите сохранить несколько связанных моделей, вы можете просто использовать метод saveAll() – 8vius

ответ

4

да оно. У меня это в моей модели приложения, чтобы упростить транзакции.

https://github.com/infinitas/infinitas/blob/dev/Model/AppModel.php#L677

/** 
    * @brief wrapper for transactions 
    * 
    * Allow you to easily call transactions manually if you need to do saving 
    * of lots of data, or just nested relations etc. 
    * 
    * @code 
    * // start a transaction 
    * $this->transaction(); 
    * 
    * // rollback if things are wrong (undo) 
    * $this->transaction(false); 
    * 
    * // commit the sql if all is good 
    * $this->transaction(true); 
    * @endcode 
    * 
    * @access public 
    * 
    * @param mixed $action what the command should do 
    * 
    * @return see the methods for tranasactions in cakephp dbo 
    */ 
    public function transaction($action = null) { 
     $this->__dataSource = $this->getDataSource(); 
     $return = false; 
     if($action === null) { 
      $return = $this->__dataSource->begin($this); 
     } else if($action === true) { 
      $return = $this->__dataSource->commit($this); 
     } else if($action === false) { 
      $return = $this->__dataSource->rollback($this); 
     } 
     return $return; 
    } 

, то вы можете сделать что-то вроде этого:

$saved = true; 
$this->transaction(); 
$saved = $saved && $this->save($data); 
$saved = $saved && $this->SomeOtherModel->save($data2); 
$saved = $saved && $this->AnotherModel->save($data3); 

if($saved){ 
$this->transaction(true); 
    return $this->id; 
} 
$this->transaction(false); 
return false; 

вы также можете сделать более сложные вещи, как следующее:

function save1(){ 

    $saved = true; 
    $this->transaction(); 
    $saved = $saved && $this->save($data); 
    $saved = $saved && $this->save2($data); 


    if($saved){ 
     $this->transaction(true); 
     return $this->id; 
    } 

    $this->transaction(false); 
    return false; 
} 

торт не поддерживает вложенные транзакции, но вы можете их подделать

// this will use transactions if its called directly, but will allow a calling method to

// create and manage the transaction.

function save2($data){ 
    $saved = true; 
    $transaction = $this->transaction(); // will only be true if not already started 
    $saved = $saved && $this->save($data); 

    if($transaction){ // if it was started here, finish it 
     if($saved){ 
      $this->transaction(true); 
      return true; 
     } 

     $this->transaction(false); 
     return false; 
    } 

    return $saved; // return just the status so the other model will finish the transaction 
} 

просто быть ясно, вы могли бы сделать что-то вроде ClassRegistry :: Init ('SomeRandomModel') -> save2(). транзакции не ограничиваются текущей моделью или связанными с ней моделями. его для любой модели.

+0

Хм, ты прав. Я думал, что функция DboSource :: begin() выполняет некоторые конкретные действия модели, поскольку Dbo требует модели в качестве параметра, но, по-видимому, она фактически не использует ее ни для чего. https://github.com/cakephp/cakephp/blob/1.3/cake/libs/model/datasources/dbo_source.php#L1799. –

+0

Практически все методы в dbo и поведении принимают модель в качестве первого параметра. Я бы подумал, что метод отправки вызовов делает это и, следовательно, даже когда он не нужен, вы его получите. – dogmatic69

+1

Торт фактически поддерживает вложенные транзакции в 2.X. См. Http://book.cakephp.org/2.0/ru/models/transactions.html # вложенные транзакции – jeffslofish

Смежные вопросы