2013-05-13 38 views
2

我有一个'AddOns'的模型,它有一堆数据。我也有标签,它们以通常的方式工作,只是就像在SO上一样,从逗号分隔的列表中最多允许5个标签。CakePHP - 将两个表手动链接在一起(向HABTM链接表中添加一个字段)

我试图创建的行为如下:

  • 用户创建上添加
  • 添加上创建
  • 系统分裂标记成一个阵列,并通过他们循环
  • 系统查找标记,如果存在,我们将使用该ID
  • 如果标记不存在,我们将创建它并使用该标识
  • 创建一个链接be补间的标签和添加

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

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 
} 
+0

您是否阅读了本书中介绍如何保存HABTM数据的部分:http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm你有,你有什么尝试? – Dave 2013-05-13 13:34:52

+0

我不确定那是我需要的。我希望在添加主记录('addon')后创建链接,引用标记表中的标记ID(假设有一个)。我将用我想要实现的一些伪代码更新这个问题 – Mike 2013-05-13 17:34:03

+0

@Dave - 我已经添加了伪代码,可能更好地解释我想要实现什么。 – Mike 2013-05-13 17:41:07

回答

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),这将限制查询三个数来提高(让现有的,创建丢失,保存),而不是每个新的标签之一,但这需要一些额外的工作handling returned IDs。如果您的用户经常会创建大量新标签,则应该这样做。

+1

这是非常宝贵的。这是不正确的,我不得不作出一些修改 - 可能更多我描述不清的问题比你的答案,但它肯定有帮助,我现在完全理解这个问题(而不是复制和粘贴解决方案)。谢谢 – Mike 2013-05-15 12:52:27

+0

不客气!我曾经有过类似的问题,所以我做了一些假设。现在你提到它,我看到你的表单必须有所不同,因为提交的数据不完全相同。 – 2013-05-15 13:01:33