/** * Updates an existing Book model. * If update is successful, the browser will be redirected to the 'view' page. * * @var Author[] $modelsAuthorNew * @param string $id Book id * @return mixed */ public function actionUpdate($id) { $modelBook = $this->findModel($id); $modelBookForm = new BookForm($modelBook); $authorsId = $modelBook->getAuthors()->select('id')->asArray()->all(); $modelsAuthor = Author::findAll($authorsId); //$modelBook->getAuthors()->asArray()->all(); if ($modelBook->load(Yii::$app->request->post())) { $modelsAuthorNew = Model::createMultiple(Author::className()); Model::loadMultiple($modelsAuthorNew, Yii::$app->request->post()); //process, separate book keyWords $modelsKeyWordsNew = [new KeyWord()]; if ($wordsArray = $modelBookForm->prepareKeyWords(Yii::$app->request->post('KeyWord')['words'])) { $modelsKeyWordsNew = Model::createMultiple(KeyWord::className(), [], $wordsArray); // KeyWord[0]['word' =>'php'] Model::loadMultiple($modelsKeyWordsNew, $wordsArray, ''); } $valid = $modelBook->validate(); $valid = Model::validateMultiple($modelsAuthorNew) && $valid; $valid = $wordsArray === false ? $valid : Model::validateMultiple($modelsKeyWordsNew) && $valid; if ($valid && $modelBookForm->updateBook($modelsAuthor, $modelsAuthorNew, $modelsKeyWordsNew)) { Yii::$app->session->setFlash('success', Yii::t('app', Yii::t('app', 'Book was updated successfully.'))); Yii::info($id . '_update', 'book'); return $this->redirect(['view', 'id' => $modelBook->id]); } else { //get all errors from multiple models if (($msg = BookForm::getErrorsMessages($modelsAuthorNew)) !== false) { Yii::$app->session->addFlash('danger', $msg); } if (($msg = BookForm::getErrorsMessages($modelsKeyWordsNew)) !== false) { Yii::$app->session->addFlash('danger', $msg); } } Yii::$app->session->addFlash('danger', Yii::t('app', 'Book was not updated.')); } return $this->render('update', ['modelBook' => $modelBook, 'modelsAuthor' => empty($modelsAuthor) ? [new Author()] : $modelsAuthor, 'keyWords' => $modelBookForm->getKeyWords()]); }
/** * 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; }
/** * @return \yii\db\ActiveQuery */ public function getAuthors() { return $this->hasMany(Author::className(), ['id' => 'author_id'])->viaTable('book_author', ['book_id' => 'id']); }