/** * update book and all related parameters * if unchanged Author already exist do nothing, otherwise delete all old authors and create new * the same with KeyWord-s * - if author or key word already exist new book is assigned to him, if not they are created * - transaction is for consistent data (book, authors, key words) * * @param Author[] $modelsAuthor * @param Author[] $modelsAuthorNew * @var KeyWord[] $modelsKeyWordsNew * @return bool - true if transaction(update) is successful otherwise false * @throws \yii\db\Exception */ public function updateBook($modelsAuthor, &$modelsAuthorNew, &$modelsKeyWordsNew) { $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { if ($flag = $this->modelBook->save(false)) { //Authors - filter unchanged Authors foreach ($modelsAuthorNew as $authorNewKey => $authorNew) { foreach ($modelsAuthor as $authorKey => $author) { if ($authorNew->first_name === $author->first_name && $authorNew->last_name === $author->last_name) { unset($modelsAuthorNew[$authorNewKey], $modelsAuthor[$authorKey]); } } } //delete all unused (old) Authors(link table record), if model Author is the last one, delete Author itself too foreach ($modelsAuthor as $ma) { $maid = $ma->id; if (($count = $db->createCommand('SELECT COUNT(*) FROM book_author WHERE author_id = :author_id')->bindParam(':author_id', $maid)->queryScalar()) !== false) { $db->createCommand()->delete('book_author', ['author_id' => $ma->id, 'book_id' => $this->modelBook->id])->execute(); if ($count == 1) { $ma->delete(); } } } //add new Authors foreach ($modelsAuthorNew as $authorNew) { if (($existA = Author::findOne(['first_name' => $authorNew->first_name, 'last_name' => $authorNew->last_name])) !== null) { $this->modelBook->link('authors', $existA); } else { if (!($flag = $authorNew->save(false))) { throw new Exception("Failed save new Authors in update book model action."); } $this->modelBook->link('authors', $authorNew); } } //KeyWords - filter unchanged words $keyWordIds = $this->modelBook->getKeyWords()->select('id')->asArray()->all(); $modelsKeyWords = KeyWord::findAll($keyWordIds); foreach ($modelsKeyWordsNew as $keyWordNewKey => $keyWordNew) { foreach ($modelsKeyWords as $keyWordKey => $keyWord) { if ($keyWordNew->word === $keyWord->word) { unset($modelsKeyWordsNew[$keyWordNewKey], $modelsKeyWords[$keyWordKey]); } } } //delete all old KeyWords foreach ($modelsKeyWords as $mkw) { $mkwid = $mkw->id; if (($count = $db->createCommand('SELECT COUNT(*) FROM book_key_word WHERE key_word_id = :key_word_id')->bindParam(':key_word_id', $mkwid)->queryScalar()) !== false) { $db->createCommand()->delete('book_key_word', ['key_word_id' => $mkw->id, 'book_id' => $this->modelBook->id])->execute(); if ($count == 1) { $mkw->delete(); } } } //save new keys if ($flag) { foreach ($modelsKeyWordsNew as $keyWordNew) { if (($existKey = KeyWord::findOne(['word' => $keyWordNew->word])) !== null) { $this->modelBook->link('keyWords', $existKey); } else { if (!($flag = $keyWordNew->save(false))) { throw new Exception("Failed save key words in update book action."); } $this->modelBook->link('keyWords', $keyWordNew); } } } } if ($flag) { $transaction->commit(); return true; } } catch (\Exception $e) { \Yii::warning($e->getMessage()); $transaction->rollBack(); return false; } return false; }