=====第十三天标签======= // 原文:http://www.symfony-project.com/askeet/13 // **回顾:** 目前的askeet程序已具有网页服务,RRS和发电子邮件等功能。使用者能提问题,其问题也能被其他用户回答。但目前的askeet仍缺乏分类的机制。就拿对问题分类来说,我们可用树状结构对问题分门别类,最终生成几百个类别。这样会对查询造成极度的不便。 然而,web 2.0 引进了一种新的管理类别的方法:标签。与树状结构中的类别不同的是,标签不依赖等级来分类,而且一条目可拥有多标签。例如,猫,用树状结构分类可编排在条目 动物/哺乳动物/四脚的/猫科。用标签就简单多了,例如用 宠物+灵俐 来描述猫。其好处是所有的用户能为自己的问题分类(加标签),更易于查询。这就是[[http://en.wikipedia.org/wiki/Folksonomy|大众分类法]] =====QuestionTag类===== {{symfony:13:mcd3.gif|}} ====Schema update==== ...
$ symfony propel-build-model
====Custom class==== $word) { if ($word == '"') { $delim++; continue; } if (($delim % 2 == 1) && $words[$key - 1] == '"') { $tags[] = trim($word); } else { $tags = array_merge($tags, preg_split('/\s+/', trim($word), -1, PREG_SPLIT_NO_EMPTY)); } } return $tags; } } ?> ====Extend the model==== public function setTag($v) { parent::setTag($v); $this->setNormalizedTag(Tag::normalize($v)); } ====Add some test data==== QuestionTag: t1: { question_id: q1, user_id: fabien, tag: relatives } t2: { question_id: q1, user_id: fabien, tag: girl } t4: { question_id: q1, user_id: francois, tag: activities } t6: { question_id: q2, user_id: francois, tag: 'real life' } t5: { question_id: q2, user_id: fabien, tag: relatives } t5: { question_id: q2, user_id: fabien, tag: present } t6: { question_id: q2, user_id: francois, tag: 'real life' } t7: { question_id: q3, user_id: francois, tag: blog } t8: { question_id: q3, user_id: francois, tag: activities }
$ php batch/load_data.php
=====Display the tags of a question=====
$ symfony init-module frontend tag
====Extend model==== public function getTags() { $c = new Criteria(); $c->clearSelectColumns(); $c->addSelectColumn(QuestionTagPeer::NORMALIZED_TAG); $c->add(QuestionTagPeer::QUESTION_ID, $this->getId()); $c->setDistinct(); $c->addAscendingOrderByColumn(QuestionTagPeer::NORMALIZED_TAG); $tags = array(); $rs = QuestionTagPeer::doSelectRS($c); while ($rs->next()) { $tags[] = $rs->getString(1); } return $tags; } ====Modify the view==== showSuccess: components: sidebar: [sidebar, question] public function executeQuestion() { $this->question = QuestionPeer::getQuestionFromTitle($this->getRequestParameter('stripped_title')); }

question tags

  • tag: url: /tag/:tag param: { module: tag, action: show } ====Test it==== #hori_border[ http://askeet/question/what-can-i-offer-to-my-step-mother ]# {{symfony:askeet:13:tag_list_question.gif|}} =====Display a short list of popular tags for a question===== ====Extend the model==== SELECT normalized_tag AS tag, COUNT(normalized_tag) AS count FROM question_tag WHERE question_id = $id GROUP BY normalized_tag ORDER BY count DESC LIMIT $max public function getPopularTags($max = 5) { $tags = array(); $con = Propel::getConnection(); $query = ' SELECT %s AS tag, COUNT(%s) AS count FROM %s WHERE %s = ? GROUP BY %s ORDER BY count DESC '; $query = sprintf($query, QuestionTagPeer::NORMALIZED_TAG, QuestionTagPeer::NORMALIZED_TAG, QuestionTagPeer::TABLE_NAME, QuestionTagPeer::QUESTION_ID, QuestionTagPeer::NORMALIZED_TAG ); $stmt = $con->prepareStatement($query); $stmt->setInt(1, $this->getId()); $stmt->setLimit($max); $rs = $stmt->executeQuery(); while ($rs->next()) { $tags[$rs->getString('tag')] = $rs->getInt('count'); } return $tags; } ====Modify the view==== getResults() as $question): ?>
    $question)) ?>

    getTitle(), '@question?stripped_title='.$question->getStrippedTitle()) ?>

    asked by getUser(), '@user_profile?nickname='.$question->getUser()->getNickname()) ?> on getCreatedAt(), 'f') ?>
    getHtmlBody()), 200) ?>
    tags:
    function tags_for_question($question, $max = 5) { $tags = array(); foreach ($question->getPopularTags($max) as $tag => $count) { $tags[] = link_to($tag, '@tag?tag='.$tag); } return implode(' + ', $tags); } ====Test==== #hori_border[http://askeet/]# {{symfony:askeet:13:popular_tags_question_list.gif|}} =====Display the list of questions tagged with a word===== ====The tag/show action==== public function executeShow() { $this->question_pager = QuestionPeer::getPopularByTag($this->getRequestParameter('tag'), $this->getRequestParameter('page')); } ====Extend the model==== public static function getPopularByTag($tag, $page) { $c = new Criteria(); $c->add(QuestionTagPeer::NORMALIZED_TAG, $tag); $c->addDescendingOrderByColumn(QuestionPeer::INTERESTED_USERS); $c->addJoin(QuestionTagPeer::QUESTION_ID, QuestionPeer::ID, Criteria::LEFT_JOIN); $pager = new sfPropelPager('Question', sfConfig::get('app_pager_homepage_max')); $pager->setCriteria($c); $pager->setPage($page); $pager->init(); return $pager; } ====Create the template====

    popular questions for tag "get('tag') ?>"

    $question_pager, 'rule' => '@tag?tag=.'$sf_params->get(tag))) ?>
    ====Add the page parameter in the routing rule==== tag: url: /tag/:tag/:page param: { module: tag, action: show, page: 1 } ====Test it==== #hori_border[http://askeet/tag/activities]# {{symfony:askeet:13:tagged_question_list.gif|}} =====See you Tomorrow=====