繁体   English   中英

确保与Phalcon相关的nn模型的唯一性

[英]Ensuring uniqueness in Phalcon related n-n models

我有一个模型contents ,该contents_tags通过中介表contents_tagstags有很多关系。 当我在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM