我的网站上有文章,我希望能够按标签订购。每篇文章都有一些标签相关联。
我使用3个表:
medias (代表文章)
+----+--------+-----+
| id | title | ... |
+----+--------+-----+
| 1 | hello | ... |
| 2 | hi | ... |
+----+--------+-----+
标签
+----+------+-----+
| id | name | ... |
+----+------+-----+
| 1 | red | ... |
| 2 |square| ... |
+----+------+-----+
medias_tags (为了将标签和媒体链接在一起)
+----+----------+--------+
| id | media_id | tag_id |
+----+----------+--------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 2 |
+----+----------+--------+
到目前为止,我正在使用这个MySQL / PHP代码按标签订购文章,这是有效的(我故意删除了分页条件以便更好地理解):
$ BDD
try{
$bdd = new PDO('mysql:host=localhost;dbname=DB;charset=utf8', 'username', 'pass');}catch(Exception $e) { die('Erreur : '.$e->getMessage());
}
if(isset($_GET['tag'])){
$tag_name_1 = htmlspecialchars($_GET['tag']);
$req_tag = $bdd->prepare('SELECT * FROM tags WHERE name = ?');
$req_tag->execute(array($tag_name_1));
$data_tag = $req_tag->fetch();
$ttag_id = $data_tag['id'];
$q = 'SELECT *
FROM medias
JOIN medias_tags
ON medias.id=medias_tags.media_id
WHERE medias_tags.tag_id ='.$ttag_id.'
ORDER BY date DESC
LIMIT '.$start.','.$limit;
}
$req_mda_list = $bdd->query($q);
问题是当我想显示与文章相关的所有标签时。 $ mda_tags_list 为空。
while ($data_mda = $req_mda_list->fetch()){
$mda_id = $data_mda['id'];
$mda_title = $data_mda['title'];
#Get media tags
$req_mda_tags = $bdd->prepare('SELECT * FROM medias_tags WHERE media_id = ?');
$req_mda_tags->execute(array($mda_id));
$mda_tags_list = null;
while ($data_mda_tags = $req_mda_tags->fetch()){
$tag_id = $data_mda_tags['tag_id'];
$req_tag_name = $bdd->prepare('SELECT * FROM tags WHERE id = ?');
$req_tag_name->execute(array($tag_id));
$data_tag_name = $req_tag_name->fetch();
$mda_tags_list .= '<a href="http://www.website.com/tags/'.$data_tag_name['name'].'">'.$data_tag_name['name'].'</a> ';
}
echo $mda_title.' - '.$mda_tags_list;
}
我真正得到的是:
Order by tag -> Square
Title1 - Tag :
Title5 - Tag :
Title6 - Tag :
我想要的是:
Order by tag -> Square
Title1 - Tag : Square, Red, Thank
Title5 - Tag : Yellow, Square, You
Title6 - Tag : Square, Blue, Stackoverflow
答案 0 :(得分:1)
要让媒体获取所有标签,您可以使用以下查询:
SELECT medias.id,medias.title,GROUP_CONCAT(tags.name) as tag
FROM medias
JOIN medias_tags ON medias.id = medias_tags.media_id
JOIN tags ON medias_tags.tag_id = tags.id
GROUP BY medias.id
要获取所有媒体以及标签(如果可用,则为空白),您可以使用以下查询:
SELECT medias.id,medias.title,GROUP_CONCAT(tags.name) as tag
FROM medias
LEFT JOIN medias_tags ON medias.id = medias_tags.media_id
LEFT JOIN tags ON medias_tags.tag_id = tags.id
GROUP BY medias.id
答案 1 :(得分:1)
我所做的是简化你的代码,我把你的SQL减少到一个语句,我添加了一些非常基本的错误检查:
$tagName = htmlspecialchars($_GET['tag']);
$sql = "SELECT
medias.*,
GROUP_CONCAT(tags2.name) AS allTags
FROM
medias
-- Get the media tags
JOIN medias_tags ON medias.id = medias_tags.media_id
-- Join on the tags so we can add a where condition
JOIN tags ON medias_tags.tag_id = tags.id
-- Rejoin tags again, this won't be used as a condition hence the left
LEFT JOIN tags AS tags2 ON medias_tags.tag_id = tags2.id
WHERE
-- Only get medias where it has a matching tag name
tag.name = :name
GROUP BY
medias.id
ORDER BY
date DESC
LIMIT
:offset, :limit";
$sth = $bdd->prepare($sql);
// Did it prepare ok?
if (!$sth) {
echo "\nPDO::errorInfo():\n";
print_r($dbh->errorInfo());
exit;
}
$err = $sth->execute(array(':name' => $tagName, ':offset' => $start, ':limit' => $limit));
// Did it execute ok?
if (!$sth) {
echo "\nPDO::errorInfo():\n";
print_r($dbh->errorInfo());
exit;
}
foreach ($sth->fetchAll() as $row) {
$tags = explode(',', $row['allTags']);
echo $row['title'] . ' - ';
foreach ($tags as $tag) {
echo '<a href="http://www.website.com/tags/' . $tag . '">' . $tag . '</a> ';
}
}
我的SQL注释可能需要删除,如果您的标记包含逗号,这也无法正常工作。如果需要,您可以指定不同的分隔符以避免这种情况。
基本上,只是减少可能失败的区域并抓住可能的区域。我只是试图按照你的例子输出你的代码看起来像什么,希望这能为你提供一些可以实现目标的东西。