2

我有一个“AddOns”模型,其中包含一堆数据。我还有标签,它们以通常的方式工作,就像在 SO 上一样,允许来自逗号分隔列表的最多 5 个标签。

我试图创建的行为如下:

  • 用户创建附加
  • 附加组件已创建
  • 系统将标签拆分成一个数组并循环遍历它们
  • 系统查找标签,如果存在,我们将使用该 ID
  • 如果标签不存在,我们将创建它并使用该 ID
  • 在标签和附加组件之间创建链接

我可以使用手动查询很容易地做到这一点,但我不确定这是最好的方法或我应该如何处理这个问题。这是我的代码:

if ($this->request->is('post')) {
$this->AddOn->create();
$this->AddOn->set('user_id', $this->Auth->user('id'));
if ($this->AddOn->save($this->request->data)) {

    // Get the ID of the addon
    $addon_id = $this->AddOn->getInsertID();
    $tagsarr = explode(',', $this->request->data['Tag']['Tag']);
    foreach($tagsarr as $tag){
        $tagdb = $this->Tags->findByTagName(trim($tag));
        if(!empty($tagdb)){
            // HELP! We have a tag, but how do we add the link?
        } else {
            // Add the tag, but then how do we link it?
        }
        unset($tagdb);
    }

    $this->Session->setFlash(
        __('The %s has been saved', __('add on'))           
    );
    $this->redirect(array('action' => 'index'));
} else {
    $this->Session->setFlash(
        __('The %s could not be saved. Please, try again.', __('add on')),
    );
}
}

编辑:在我想要实现的目标下面添加了一些伪代码。

$AddOn->create();
$AddOn->save(); // Create AddOn
$AddOnID = $AddOn->insertId(); // Newly inserted AddOn's ID

$tagsArr = explode(',', $post->tags); // Make an array of tags [this,is,a,tag,list]
foreach($tagsArr as $tag){ // Loop through them
  $tagFromDb = $Tags->findTagByName($tag); // Try and find the tag from the tags table
  if(!$tagFromDb){ // Have we found it? No
    $tagId = $Tags->newTag($tag); // Add it and reference
  } else { // Have we found it? Yes
    $tagId = $tagFromDb->id; // Reference it
  }
  $AddOnTagsLink->addAddOnTagsLink($AddOnID, $tagId); // Add the link
}
4

1 回答 1

1

实现这一点的逻辑应该在模型中,而不是在控制器中。使用 before save 回调允许我们在表单中添加一个“tags”字段并正常保存。

public function beforeSave($options = array()) {
    if (isset($this->data['AddOn']['tags'])) {
        $this->data['Tag'] = array();
        $submitted = array_map('trim', explode(',', $this->data['AddOn']['tags']));
        $existing = $this->Tag->find('list', array(
            'fields' => array('id', 'name'),
            'conditions' => array('name' => $submitted),
            'recursive' => -1
        ));
        foreach ($submitted as $tag) {
            if(!empty($tag)) {
                $id = array_search($tag, $existing);
                if (!$id) {
                    $this->Tag->save(array('name' => $tag));
                    $id = $this->Tag->id;
                }
                $this->data['Tag'][] = array('tag_id' => $id);
            }
        }
    }
    return true;
}

可以通过使用一个查询(使用saveAll)保存所有新标签来改进该代码,这会将查询的数量限制为三个(获取现有、创建缺失、保存)而不是每个新标签一个,但这需要一些额外的处理工作返回的 ID。如果您的用户会经常创建大量新标签,您应该这样做。

于 2013-05-13T23:56:30.147 回答