【问题标题】:Ensuring uniqueness in Phalcon related n-n models确保 Phalcon 相关 n-n 模型的唯一性
【发布时间】:2014-09-19 07:24:08
【问题描述】:

我有一个模型contents,它通过中间表contents_tagstags 具有多对多关系。当我在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  |
+----+--------+

上面提到的单元测试模型似乎没有设置特殊参数,我找不到它们的实际表声明,所以我有点茫然。单元测试的模型可以在这里看到:

【问题讨论】:

    标签: php model phalcon


    【解决方案1】:

    这是我对单元测试在做什么的误解。我认为它注意到“第 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-15
      • 2013-03-15
      • 1970-01-01
      • 2013-08-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      相关资源
      最近更新 更多