CakePHP标签模型

时间:2014-01-16 13:27:59

标签: php cakephp

我有一个简单的应用程序,其中包含帖子和标签。

帖子可以有多个标签,标签可以属于多个帖子。基本的DB模式是这样的:

帖子表:

id
title
slug
content

标签表:

id
title
slug

tag_posts表:

id
tag_id
post_id

因此,当用户保存帖子时,它会在字段中获取标签列表,然后首先检查标签是否存在。如果标记不存在,则创建它们,或者如果不存在则存在。 (所有标记都是低级的,因此您无法拥有Tagtag)。然后通过将id添加到tag_posts表中来将标签链接到帖子。

到目前为止这是有效的,但执行它的代码真的很糟糕。我在Tag模型中有以下方法,它采用标签列表并执行上述操作:

公共函数savePostTags($ postId,$ tags) {

// Explode the topics by comma, so we have an array to run through
$tags = explode(',', $tags);
// Array for collecting all the data
$collection = array();

//debug($tags);

function is_array_empty( $mixed ) {
    if ( is_array($mixed) ) {
        foreach ($mixed as $value) {
            if ( ! is_array_empty($value) ) {
                return false;
            }
        }
    } elseif ( ! empty($mixed) ) {
        return false;
    }

    return true;
}

if(is_array_empty($tags) ) {

    return false;

}

// First of all we bin off existing associations to make sure we don't duplicate
// NOTE: The false means don't delete the topics or posts related!!! VERY IMPORTANT!
$this->TagPost->deleteAll(array('TagPost.post_id' => $postId), false);

$tags = array_unique($tags);

// Make sure all tags are unique

foreach($tags as $tag)
{
    // Trim it so remove unwanted white spaces in the beginning and the end.
    $tag = trim($tag);

    // If tag is empty exit here
    if(empty($tag) ) {

        return false;

    }

    // Make it all lowercase for consistency of tag names
    $tag = strtolower($tag);

    // Check if we already have a topic like this
    $controlFind = $this->find(
        'first',
        array(
            'conditions' => array(
                'title' => $tag
            )
        )
    );

    //debug($controlFind);

    // No record found (create new tag and link it up)
    if(!$controlFind)
    {
        $this->create();
        if(
            !$this->save(
                array(
                    'title' => $tag,
                    'slug' => Inflector::slug($tag)
                )
            )
        )
        {
            // If only one saving fails we stop the whole loop and method.
            return false;
        }
        else
        {
            $temp = array(
                'TagPost' => array(
                    'tag_id' => $this->id,
                    'post_id' => $postId
                )
            );
        }
    }
    else // Or if found link it with the post
    {
        $temp = array(
            'TagPost' => array(
                'tag_id' => $controlFind['Tag']['id'],
                'post_id' => $postId
            )
        );
    }

    $collection[] = $temp;
}

return $this->TagPost->saveAll($collection, array('validate' => false));

}

关于如何重构这个的任何想法?

因为感觉真的很啰嗦,似乎打破了CakePHP的惯例。

2 个答案:

答案 0 :(得分:0)

试试这个

   public function savePostTags($postId, $tags)
        {
            $tags = explode(',', $tags);
            foreach($tags as $key=>$value){
              $listTags[$key] = trim(strtolower($value));    
            }
            # find the list of existing tags
            $listOfExistingTags = $this->find('list',
                         array('conditions' => array('title' => $tags),
                         'recursive' => -1));
            $newTags = array_diff($tags, $listOfExistingTags);
            #save new tags
            foreach($newTags as $key=>$value){
                 $saveData[$key]['Tag']['title'] =  $value;
                 $saveData[$key]['Tag']['slug']  =  Inflector::slug($value);
             }
            if(!empty($saveData))$this->saveAll($saveData);
            # this save all the tags
            # now save data in tag_posts
            $listOfExistingTags = $this->find('list',
               array('conditions' =>array('title' => $tags),
                     'fields'=>array('id','title'),
                     'recursive' => -1));  
            $i = 0;
            foreach($listOfExistingTags as $key=>$value){
                $tagPostData[$i]['TagPost']['tag_id']  = $key;  
                $tagPostData[$i]['TagPost']['post_id'] = $postId; $i++; 
            }
            if(!empty($tagPostData)){
            App::import('model','TagPost');
            $TagPost = new TagPost();
            $TagPost->saveAll($tagPostData);
           }
        }

答案 1 :(得分:0)

  

关于如何重构这个的任何想法?

使用the CakeDC Tags plugin。它经过单元测试,易于投入,耗时约15分钟。看到它的readme.md。它基本上只是添加行为并在表单中添加字段“tags”。