=====第十三天标签=======
// 原文: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=====