/** * Creates a new model. */ public function actionCreate() { /** @var BaseActiveRecord $model */ $model = new $this->modelClass('create'); $this->performAjaxValidation($model); $model->attributes = Yii::app()->request->getParam($this->modelClass, array()); if (Yii::app()->request->isPostRequest && !Yii::app()->request->isAjaxRequest) { $transaction = $model->getDbConnection()->beginTransaction(); try { $model->save(); $transaction->commit(); $url = array('update', 'id' => $model->primaryKey); $this->redirect($url); } catch (Exception $e) { $transaction->rollback(); } } $this->render('create', array('model' => $model)); }
/** * Class DbTransaction * Stores models states for restoring after rollback. */ class DbTransaction extends CDbTransaction { /** @var BaseActiveRecord[] models with stored states */ private $_models = array(); /** * Checks if model state is already stored. * @param BaseActiveRecord $model * @return boolean */ public function isModelStateStoredForRollback($model) { return in_array($model, $this->_models, true); } /** * Stores model state for restoring after rollback. * @param BaseActiveRecord $model */ public function storeModelStateForRollback($model) { if (!$this->isModelStateStoredForRollback($model)) { $model->storeState(false); $this->_models[] = $model; } } /** * Rolls back a transaction. * @throws CException if the transaction or the DB connection is not active. */ public function rollback() { parent::rollback(); foreach ($this->_models as $model) { $model->restoreState(); } $this->_models = array(); } }
abstract class BaseActiveRecord extends CActiveRecord { /** @var array */ protected $_storedState = array(); /** * * @return boolean */ public function hasStoredState() { return $this->_storedState !== array(); } /** * * @param boolean $force * @return void */ public function storeState($force = false) { if (!$this->hasStoredState() || $force) { $this->_storedState = array( 'isNewRecord' => $this->isNewRecord, 'attributes' => $this->getAttributes(), ); } } /** * * @return void */ public function restoreState() { if ($this->hasStoredState()) { $this->isNewRecord = $this->_storedState['isNewRecord']; $this->setAttributes($this->_storedState['attributes'], false); $this->_storedState = array(); } } }
/** * Creates a new model. */ public function actionCreate() { /** @var BaseActiveRecord $model */ $model = new $this->modelClass('create'); $this->performAjaxValidation($model); $model->attributes = Yii::app()->request->getParam($this->modelClass, array()); if (Yii::app()->request->isPostRequest && !Yii::app()->request->isAjaxRequest) { $transaction = $model->getDbConnection()->beginTransaction(); // $transaction->storeModelStateForRollback($model); try { $model->save(); $transaction->commit(); $url = array('update', 'id' => $model->primaryKey); $this->redirect($url); } catch (Exception $e) { $transaction->rollback(); } } $this->render('create', array('model' => $model)); }
abstract class BaseActiveRecord extends CActiveRecord { // ... /** * ( ) * @param boolean $runValidation * @param array $attributes * @throws Exception|UserException * @return boolean */ public function save($runValidation = true, $attributes = null) { /** @var DbTransaction $transaction */ $transaction = $this->getDbConnection()->getCurrentTransaction(); $isExternalTransaction = ($transaction !== null); if ($transaction === null) { $transaction = $this->getDbConnection()->beginTransaction(); } $transaction->storeModelStateForRollback($this); $exception = null; try { $result = parent::save($runValidation, $attributes); } catch (Exception $e) { $result = false; $exception = $e; } if ($result) { if (!$isExternalTransaction) { $transaction->commit(); } } else { if (!$isExternalTransaction) { $transaction->rollback(); } throw $exception; } return $result; } // ... }
Source: https://habr.com/ru/post/198100/
All Articles