From 14cd7eed2849cf5ca2b52e8caaaf957f9ea0d0e3 Mon Sep 17 00:00:00 2001 From: yarik Date: Mon, 10 Oct 2016 18:33:29 +0300 Subject: [PATCH] LanguageBehavior optimized --- backend/controllers/ArticlesController.php | 14 ++++++-------- common/models/Articles.php | 64 ++++++++++++++++------------------------------------------------ common/modules/language/behaviors/LanguageBehavior.php | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------- common/modules/language/readme.txt | 19 ++++++++----------- 4 files changed, 112 insertions(+), 88 deletions(-) diff --git a/backend/controllers/ArticlesController.php b/backend/controllers/ArticlesController.php index 6a3f3e0..34d4258 100755 --- a/backend/controllers/ArticlesController.php +++ b/backend/controllers/ArticlesController.php @@ -82,10 +82,9 @@ public function actionCreate() { $model = new Articles(); - $model_langs = $model->generateLangs(); + $model->generateLangs(); if($model->load(Yii::$app->request->post())) { - $model->loadLangs(\Yii::$app->request, $model_langs); - $model->model_langs = $model_langs; + $model->loadLangs(\Yii::$app->request); if($model->save() && $model->transactionStatus) { return $this->redirect([ 'view', @@ -95,7 +94,7 @@ } return $this->render('create', [ 'model' => $model, - 'model_langs' => $model_langs, + 'model_langs' => $model->model_langs, ]); } @@ -110,10 +109,9 @@ public function actionUpdate($id) { $model = $this->findModel($id); - $model_langs = $model->generateLangs(); + $model->generateLangs(); if($model->load(Yii::$app->request->post())) { - $model->loadLangs(\Yii::$app->request, $model_langs); - $model->model_langs = $model_langs; + $model->loadLangs(\Yii::$app->request); if($model->save() && $model->transactionStatus) { return $this->redirect([ 'view', @@ -123,7 +121,7 @@ } return $this->render('update', [ 'model' => $model, - 'model_langs' => $model_langs, + 'model_langs' => $model->model_langs, ]); } diff --git a/common/models/Articles.php b/common/models/Articles.php index 6a7be6d..eb9c661 100755 --- a/common/models/Articles.php +++ b/common/models/Articles.php @@ -1,7 +1,7 @@ SaveImgBehavior::className(), + 'class' => SaveImgBehavior::className(), 'fields' => [ [ - 'name' => 'image', + 'name' => 'image', 'directory' => 'articles', - ] + ], ], ], 'language' => [ 'class' => LanguageBehavior::className(), ], - 'transaction' => [ - 'class' => TransactionBehavior::className(), - ], ]; } @@ -93,22 +87,6 @@ 'safe', ], [ - [ - 'image', - ], - 'string', - 'max' => 255, - ], - [ - [ 'imageUpload' ], - 'safe', - ], - [ - [ 'imageUpload' ], - 'file', - 'extensions' => 'jpg, gif, png', - ], - [ [ 'date' ], 'filter', 'filter' => function($value) { @@ -124,23 +102,13 @@ public function attributeLabels() { return [ - 'id' => Yii::t('app', 'ID'), - 'date' => Yii::t('app', 'Date'), - 'image' => Yii::t('app', 'Image'), - 'imageUrl' => Yii::t('app', 'Image'), + 'id' => Yii::t('app', 'ID'), + 'date' => Yii::t('app', 'Date'), + 'image' => Yii::t('app', 'Image'), + 'imageUrl' => Yii::t('app', 'Image'), ]; } - public function getImageFile() - { - return empty( $this->image ) ? NULL : Yii::getAlias('@imagesDir/articles/' . $this->image); - } - - public function getImageUrl() - { - return empty( $this->image ) ? NULL : Yii::getAlias('@imagesUrl/articles/' . $this->image); - } - public function recalculateRating() { /** diff --git a/common/modules/language/behaviors/LanguageBehavior.php b/common/modules/language/behaviors/LanguageBehavior.php index c97508e..19513db 100755 --- a/common/modules/language/behaviors/LanguageBehavior.php +++ b/common/modules/language/behaviors/LanguageBehavior.php @@ -6,15 +6,16 @@ use yii\base\InvalidConfigException; use yii\db\ActiveQuery; use yii\db\ActiveRecord; + use yii\db\Transaction; use yii\web\Request; /** * Class LanguageBehavior - * @property ActiveRecord $owner - * @property string $ownerKey - * @property string $langKey + * @property ActiveRecord $owner + * @property string $ownerKey + * @property string $langKey * @property ActiveRecord[] $langs - * @property ActiveRecord $lang + * @property ActiveRecord $lang */ class LanguageBehavior extends Behavior { @@ -24,11 +25,36 @@ */ public $object_lang; + /** + * @var ActiveRecord[] $model_langs + */ + public $model_langs = []; + private $_owner_key; private $_lang_key; /** + * @var Transaction $_transaction + */ + private $_transaction; + + /** + * @var bool $_transaction_status + */ + private $_transaction_status = false; + + public function events() + { + return [ + ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave', + ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeSave', + ActiveRecord::EVENT_AFTER_INSERT => 'afterSave', + ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave', + ]; + } + + /** * Get $owner primary key to link language model * @return string */ @@ -129,19 +155,20 @@ $table_name = $object_lang::getTableSchema()->name; $owner = $this->owner; return $owner->hasOne($object_lang::className(), [ $this->getLangKey() => $this->getOwnerKey() ]) - ->where([ $table_name.'.language_id' => $language_id ]); + ->where([ $table_name . '.language_id' => $language_id ]); } /** * Generate language models for $owner for active languages. If $owner not new and language * models already inserted, models will be filled with them. - * @return ActiveRecord[] + * @return void */ public function generateLangs() { $owner = $this->owner; $languages = Language::find() ->where([ 'status' => true ]) + ->orderBy([ 'language_id' => SORT_ASC ]) ->asArray() ->column(); $object_lang = $this->object_lang; @@ -150,6 +177,7 @@ if(!$owner->isNewRecord) { $langs = $this->getLangs() ->andFilterWhere([ 'language_id' => $languages ]) + ->orderBy([ 'language_id' => SORT_ASC ]) ->all(); } foreach($languages as $language) { @@ -161,21 +189,20 @@ ]); } } - return $langs; + $this->model_langs = $langs; } /** * Load language models with post data. * - * @param Request $request - * @param ActiveRecord[] $model_langs + * @param Request $request */ - public function loadLangs(Request $request, array $model_langs) + public function loadLangs(Request $request) { foreach($request->post($this->object_lang->formName(), []) as $lang => $value) { - if(!empty( $model_langs[ $lang ] )) { - $model_langs[ $lang ]->attributes = $value; - $model_langs[ $lang ]->language_id = $lang; + if(!empty( $this->model_langs[ $lang ] )) { + $this->model_langs[ $lang ]->attributes = $value; + $this->model_langs[ $lang ]->language_id = $lang; } } } @@ -183,12 +210,9 @@ /** * Link language models with $owner by setting language model language key to owner key of * owner - * - * @param ActiveRecord[] $model_langs - * * @return bool If $owner is new record then return false else true */ - public function linkLangs(array $model_langs) + public function linkLangs() { $owner = $this->owner; if($owner->isNewRecord) { @@ -196,6 +220,7 @@ } $lang_key = $this->getLangKey(); $owner_key = $this->getOwnerKey(); + $model_langs = $this->model_langs; foreach($model_langs as $model_lang) { $model_lang->$lang_key = $owner->$owner_key; } @@ -204,14 +229,12 @@ /** * Try to save all language models to the db. Validation function is run for all models. - * - * @param ActiveRecord[] $model_langs - * * @return bool Whether all models are valid */ - public function saveLangs(array $model_langs) + public function saveLangs() { $success = true; + $model_langs = $this->model_langs; foreach($model_langs as $model_lang) { if(!$model_lang->save()) { $success = false; @@ -219,4 +242,42 @@ } return $success; } + + public function beforeSave($event) + { + /** + * @var ActiveRecord $owner + */ + $owner = $this->owner; + $db = $owner::getDb(); + $this->_transaction = $db->beginTransaction(); + } + + public function afterSave($event) + { + /** + * @var ActiveRecord $owner + */ + $owner = $this->owner; + if(!empty( $this->model_langs )) { + if($this->linkLangs() && $this->saveLangs()) { + $this->_transaction->commit(); + $this->_transaction_status = true; + } else { + $this->_transaction->rollBack(); + $this->_transaction_status = false; + } + } else { + $this->_transaction->commit(); + $this->_transaction_status = true; + } + } + + /** + * @return bool + */ + public function getTransactionStatus():bool + { + return $this->_transaction_status; + } } \ No newline at end of file diff --git a/common/modules/language/readme.txt b/common/modules/language/readme.txt index 9e85992..e25929f 100755 --- a/common/modules/language/readme.txt +++ b/common/modules/language/readme.txt @@ -57,6 +57,8 @@ public function behaviors() { * @property {TableLang} $object_lang * @property string $ownerKey * @property string $langKey + * @property {TableLang}[] $model_langs + * @property bool $transactionStatus * @method string getOwnerKey() * @method void setOwnerKey(string $value) * @method string getLangKey() @@ -67,20 +69,16 @@ public function behaviors() { * @method void loadLangs(Request $request, ActiveRecord[] $model_langs) * @method bool linkLangs(ActiveRecord[] $model_langs) * @method bool saveLangs(ActiveRecord[] $model_langs) - * * End language behavior * - * * From transaction behavior * - * @property {TableLang}[] $model_langs - * @property bool $transactionStatus * @method bool getTransactionStatus() - * * End transaction behavior * + * * End language behavior * 3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...) 4. Доступные полезные методы: {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id {Table}->getLang($language_id = NULL) - получить {TableLang} для определенного языка (default: текущий язык) для {Table} {Table}->generateLangs() - получить массив {TableLang} под каждый язык, включая существующие записи, для {Table} - {Table}->loadLangs($request, $model_langs) - заполнить массив {TableLang} данными с POST - {Table}->linkLangs($model_langs) - связать каждый элемент массива {TableLang} с текущей {Table} - {Table}->saveLangs($model_langs) - провалидировать и сохранить каждый элемент массива {TableLang} + {Table}->loadLangs($request) - заполнить массив {TableLang} данными с POST + {Table}->linkLangs() - связать каждый элемент массива {TableLang} с текущей {Table} + {Table}->saveLangs() - провалидировать и сохранить каждый элемент массива {TableLang} 5. Добавить поля в форму (к примеру через Bootstrap Tabs). В наличии: LanguageForm::widget([ @@ -90,7 +88,6 @@ public function behaviors() { ]); 6. Обрабатывать данные в контроллере. 1. После создания/поиска {Table} создаем/находим языковые модели {Table}->generateLangs() - 2. При POST запросе загружаем данные в языковые модели {Table}->loadLangs(Request $request, {TableLangs[]} $model_langs) - 3. Передаем в свойство model_langs модели {Table} массив {TableLang[]}: $model->model_langs = $model_langs - 4. После сохранения, если транзанкция успешна, то свойство {Table}->transactionStatus будет true, иначе возникла ошибка в какой то модели. + 2. При POST запросе загружаем данные в языковые модели {Table}->loadLangs(Request $request) + 3. После сохранения, если транзанкция успешна, то свойство {Table}->transactionStatus будет true, иначе возникла ошибка в какой то модели. 7. Получать данные на публичной части сайта через {Table}->lang. -- libgit2 0.21.4