我试图做一个基于标签的CMS/博客。没什么复杂的,因为这主要是一个学习练习。我使用的是PHP和MySQL,不过我怀疑如果将自定义的DB代码写到磁盘上,这会更容易。
不管怎样,我想有两个表,一个标签列表,一个名字和id,一个帖子列表,一个内容,一个标签的id列表。但是,似乎不能将整数数组放在表的单个字段中。所以我制作了第三个表posttags,它包含OwningPost和TagID。表中有多个重复的OwningPost,每个都有不同的标记id,因此一个post可以有多个标记。这看起来不太干净,但我想不出比这更好的了。
现在,我想得到一个列表,列出所有有特定标签,但没有其他特定标签的帖子。我甚至还没有找到not标签,我仍然被贴在包含指定标签的帖子上。我有这个密码:
printPostsTagged(array('Blog Post'),array('First'));
function printPostsTagged($iTags,$eTags)
{
$tagQ="SELECT ID from tags WHERE (";
for($i=0;$i<count($iTags)-1;$i++)
$tagQ=$tagQ."Name='".$iTags[$i]."' OR ";
$tagQ=$tagQ."Name='$iTags[$i]')";
$tagR=mysql_query($tagQ);
...
它通过将所有ITAG(包括的标记)与ORs串接在一起进行查询,这将得到ITAG中每个标记的ID列表,现在我想使用整个列表从posttags中选择OwningPost,然后使用该索引列表从posttags表中获取所有对应的Post列表。
我以前没有使用过SQL,但是我的google搜索似乎没有任何结果,我强烈地感觉我在这里做了完全错误的事情
最佳答案
要获得良好的表模式,请查看:http://forge.mysql.com/wiki/TagSchema#Recommended_Architecture
通常项目不是按标记“name”查询的,而是按标记id或标记slug查询的,总之,您可以使用JOIN简化您的函数:
function printPostsTagged($iTags, $eTags) {
$in = '"' . implode('", "', array_map('mysql_real_escape_string', $iTags)) . '"';
$sql = "SELECT p.* FROM posts p
INNER JOIN post_tag pt ON pt.post_id = p.post_id
INNER JOIN tags t ON pt.tag_id = t.tag_id
WHERE name IN ($in)";
// it removes duplicates and fetch just the posts with all the iTtags assigned
$sql .= " GROUP BY p.id HAVING COUNT(p.id) = " . count($iTags);
}