2014-09-19 19 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;