Yii2 - insert relational data with junction table,

2019-06-20 06:57发布

问题:

I have a problem with Yii2 (Stable).

I have a Content(PK:id) table, I have a Tag(PK:id) table, and I have a junction table called Content_Tag (PK:content_id, tag_id). I'd like to use it for tagging, like WP tags.

All controllers and models are created with gii.

I have two problems:

If I create a new content, I'd like to save some new tags to the Tag table via the Content_Tag table. How can I do that? With link()?

What if there are tags (I know the ids) in the tag table, I'd like to connect only with the Content table via the junction table, without inserting into the Tag table. How can I do this?

I don't want to write native SQL command, I'd like to use the Yii2 built in functions like link() or via() or viaTable().

Thanks for your help!

回答1:

I created a behavior to help handle do this, basically you do:

$content = Content::findOne(1);
$tags = [Tag::findOne(2), Tag::findOne(3)];
$content->linkAll('tags', $tags, [], true, true);

You can get the behavior here: https://github.com/cornernote/yii2-linkall

If you'd prefer to do it without the behavior, something like this:

// get the content model
$content = Content::findOne(1);
// get the new tags
$newTags = [Tag::findOne(2), Tag::findOne(3)];
// get the IDs of the new tags
$newTagIds = ArrayHelper::map($newTags, 'id', 'id');
// get the old tags
$oldTags = $post->tags;
// get the IDs of the old tags
$oldTagIds = ArrayHelper::map($oldTags, 'id', 'id');
// remove old tags
foreach ($oldTags as $oldTag) {
    if (!in_array($oldTag->id, $newTagIds)) {
        $content->unlink('tags', $oldTag, true);
    }
}
// add new tags
foreach ($newTags as $newTag) {
    if (!in_array($newTag->id, $oldTagIds)) {
        $content->link('tags', $newTag);
    }
}


回答2:

If you created models using gii then you might seen in the model the relationship is done like:

 /**
 * @return \yii\db\ActiveQuery
 */
public function getContent()
{
    return $this->hasMany(Content_Tag::className(), ['content_id' => 'id']);
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getContent()
{
    return $this->hasMany(Tag::className(), ['tag_id' => 'tag_id'])->viaTable('content_tag', ['content_id' => 'id']);
}

If you want to save in Content_Tag table based on Content and Tag table then in controller you can use:

public function actionCreate()
  {
    $model          = new Tag();
    $content          = new Content();
    $content_tag = new Content_tag();

    if($model->load(Yii::$app->request->post()) && $model->save()){
      $model->save(false);
      $content_tag->tag_id = $model->id;
      $content_tag->content_id = $model->content_id;
      $content_tag->save(false);
      if($model->save(false))
      {
        Yii::$app->getSession()->setFlash('success', 'Created successfully');
        return $this->render('create',[
            'model' => $model,
            'content' => $content,
            'content_tag' => $content_tag
          ]);
      }
    }
    else
    {
      return $this->render('create', [
          'model' => $model,
        ]);
    }
  }

You can use link() to save. I am also searching for that as I didn't use that.



标签: yii2