2014-09-19 20 views
0

我有一個型號爲contents,它與tags通過中間表contents_tags有多對多的關係。當我在contents中插入新行時,我還想添加多個標籤。雖然這可以正常工作,但我希望tags條目是唯一的,因此如果它們是新的,或者已更新(儘管沒有更改),它們將被插入,如果它們已經存在。確保Phalcon相關n-n型號的唯一性

This unit test似乎暗示這可以自動完成,但我無法設法複製相同的行爲。如果我的標籤表沒有唯一的索引,那麼我會得到多個相同的條目。如果我這樣做,那麼標記模型會引發錯誤。

這是我的測試代碼:

$content    = new Content(); 
$content->title   = 'xkcd'; 
$content->description = 'description goes here'; 
$content->url   = 'http://xkcd.com/'; 
$content->created_on = new Phalcon\Db\RawValue('NOW()'); 
$content->tags   = array(); 

$tagsText = 'xkcd,comics,testing'; 

$tags = array(); 
foreach(explode(',', $tagsText) as $tagText) { 
    $tag = new Tag(); 
    $tag->tag = trim($tagText); 
    $tags[] = $tag; 
} 
$content->tags = $tags; 

if($content->save()) { 
    $app->response->setStatusCode(201, "Created"); 
    $app->response->setJsonContent($content->overview()); 
} else { 
    $app->response->setStatusCode(400, "Bad Request"); 
    $app->response->setJsonContent(array('errors'=>$content->getMessagesAsArray())); 
} 

內容模型:

class Content { 
    public function initialize() { 
     $this->hasManyToMany(
      'id', 
      'ContentsTags', 
      'content_id', 
      'tag_id', 
      'Tag', 
      'id', 
      array('alias' => 'tags') 
     ); 
    } 

    public function getSource() { 
     return 'contents'; 
    } 
} 

ContentsTag型號:

class ContentsTags { 

    public function initialize() { 
     $this->belongsTo('content_id', 'Content', 'id', array('alias' => 'content')); 
     $this->belongsTo('tag_id', 'Tag', 'id', array('alias' => 'tag')); 
    } 

    public function getSource() { 
     return 'contents_tags'; 
    } 
} 

標籤模型:從表中

class Tag { 

    public function getSource() { 
     return 'tags'; 
    } 

    public function initialize() { 
     $this->hasManyToMany(
      'id', 
      'ContentsTags', 
      'tag_id', 
      'content_id', 
      'Content', 
      'id', 
      array('alias' => 'contents') 
     ); 
    } 
} 

實施例的數據:

內容:

+----+-------+-----------------------+------------------+ 
| id | title | description   | url    | 
+----+-------+-----------------------+------------------+ 
| 11 | xkcd | description goes here | http://xkcd.com/ | 
+----+-------+-----------------------+------------------+ 

contents_tags:

+----+------------+--------+ 
| id | content_id | tag_id | 
+----+------------+--------+ 
| 1 |   11 |  1 | 
| 2 |   11 |  2 | 
+----+------------+--------+ 

標籤:

+----+--------+ 
| id | tag | 
+----+--------+ 
| 1 | comics | 
| 2 | maths | 
+----+--------+ 

上述單元測試的模型似乎沒有特殊的參數設置,我找不到實際的表格聲明,所以我有點虧損。對於單元測試,該機型可以在這裏看到:

回答

0

這是什麼樣的單元測試是做了一點誤解我。我認爲它注意到「第1部分」和「第2部分」已經作爲部分存在,它實際上做的是注意到他們有一個ID,因此不需要插入。

我已將此添加標籤類:

/** 
* Look to see if a tag exists, if it does then 
* return it. If it doesn't then create it and 
* return it. 
* 
* @param string $tagName 
* @return Tag $tag 
*/ 
public static function getOrCreate($tagName) { 
    $tag = static::findFirst(
     array(
      'conditions' => "tag=?0", 
      "bind" => array($tagName) 
     ) 
    ); 
    if($tag) return $tag; 

    try { 
     $tag = new Tag(); 
     $tag->tag = $tagName; 
     $tag->save(); 
     return $tag; 
    } catch(Exception $e) { 
     $this->appendMessage(new Message($e->getMessage(), 'tags')); 
     return false; 
    } 
} 

,並改變了測試代碼如下:

$tags = array(); 
foreach(explode(',', $tagsText) as $tagText) { 
    $tags[] = Tag::getOrCreate(trim($tagText)); 
} 
$content->tags = $tags;