![](/img/trans.png)
[英]Get objects in the other part of a N-N relationship that are not related to the actual object
[英]Ensuring uniqueness in Phalcon related n-n models
我有一个模型contents
,该contents_tags
通过中介表contents_tags
与tags
有很多关系。 当我在contents
插入新行时,我还想添加多个标签。 尽管这可以正常工作,但我希望tags
条目是唯一的,因此如果tags
条目是新tags
,则将其插入;如果tags
已存在,则将对其进行更新(尽管没有任何更改)。
这个单元测试似乎暗示可以自动完成,但是我无法复制相同的行为。 如果我的标签表上没有唯一索引,那么我会得到多个相同的条目。 如果我这样做,则标记模型将引发错误。
这是我的测试代码:
$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 |
+----+--------+
上面提到的用于单元测试的模型似乎没有设置特殊的参数,并且我找不到它们的实际表声明,所以我有点茫然。 可以在此处看到用于单元测试的模型:
这是我对单元测试所做的误解。 我以为是在注意到“第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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.