我的模型contents
通过中间表tags
与contents_tags
有多对多的关系。当我在contents
中插入新行时,我还要添加多个标记。虽然这很好,但我希望tags
条目是唯一的,因此如果它们是新的,它们将被插入,或者如果它们已经存在则更新(尽管没有任何变化)。
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 :(得分:0)
这是我对单元测试正在做什么的误解。我以为它注意到"第1部分"和"第2部分"已经作为零件存在,它实际上做的是注意到它们有一个ID,因此不需要插入。
我将此添加到Tag类:
/**
* 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;