Теги (ярлыки) — один из способов структурирования материала сайта. Веб-мастер при добавлении публикации на сайт присваивает ей несколько тегов — ключевых слов, которые позволяют понять ее тематику. Впоследствии на сайте возможен отбор и поиск материала по тегам.
Некоторые теги повторяются у различных статей, такие теги становятся популярными. На этом сайте, допустим, были бы популярны теги PHP и HTML.
Облако тегов — это блок с определенным количеством самых популярных тегов сайта. При чем, чем популярнее тег, тем больше визуально он выглядит в облаке.
Хранение тегов в базе данных
Для начала определимся, каким образом можно хранить теги для статей в базе данных. Просто хранить теги через запятую в текстовом поле для каждой статьи — плохое решение, так как реализация построения облака и поиска по тегам будет очень сложной и медленной. Самый оптимальный способ, я считаю — это связь "многие ко многим" между таблицами статей и тегов при помощи промежуточной таблицы.
В простейшем случае мы имеем таблицу со статьями articles следующей структуры:
id | alias | title | text
Таблица с тегами tags может выглядеть так:
id | alias | title
Поля alias нужны для создания читаемых URL с участием этих элементов (например /articles/hello, вместо использования числового идентификатора /articles/13).
Для установления связи между статьями и тегами создается промежуточная таблица articles_tags:
id | article_id | tag_id
В ней каждая запись описывает связь какого-то тега с какой-то статьей. Таким образом, любой из тегов может быть присвоен нескольким статьям. Нужно продумать алгоритм заполнения таблиц при добавлении новой публикации, но это уже выходит за пределы темы данной статьи.
Реализация облака тегов
Итак, предположим, что мы имеем вышеописанные три таблицы с заполненными данными. Нам нужно определить самые популярные теги и построить по ним облако. При помощи переменной зададим количество тегов, которое будет отображено в облаке:
$tags_count = 30; //--Кол-во тегов в облаке
Далее необходимо составить SQL-запрос для получения самых популярных тегов. Выглядеть он может следующим образом:
SELECT tags.title AS title,
tags.alias AS alias,
COUNT(tags_articles.id) AS cnt
FROM tags
INNER JOIN articles_tags
ON ( articles_tags.tag_id = tags.id )
GROUP BY tags.id
ORDER BY cnt DESC
LIMIT %tags_count%
В результате запрос возвратит таблицу с %tags_count% самых популярных тегов следующей структуры:
заголовок тега | алиас тега | количество упоминаний
Теги в ней будут отсортированы по популярности. В таком порядке построенное облако будет выглядеть не очень красиво, поэтому рекомендую отсортировать теги по заголовкам. Это можно сделать как на PHP, так и в момент запроса, доработав немного SQL-запрос:
SELECT *
FROM (SELECT tags.title AS title,
tags.alias AS alias,
COUNT(tags_articles.id) AS cnt
FROM tags
INNER JOIN articles_tags
ON ( articles_tags.tag_id = tags.id )
GROUP BY tags.id
ORDER BY cnt DESC
LIMIT %tags_count%) AS subq
ORDER BY title
Итак, у нас имеется список самых популярных тегов. Теперь необходимо отобразить их с разной величиной (размером шрифта) в зависимости от популярности. Критерием популярности служит параметр cnt (количество упоминаний). Но использовать этот параметр как размер шрифта нельзя. Во-первых, в большой базе он будет иметь большие значения. Во-вторых, у тегов эти параметры могут сильно отличаться, нарисовать один тег в тысячу раз больше другого — плохая идея.
Объявим две переменные, задающие минимальный и максимальный размер шрифта в облаке тегов:
$min_real = 8; //--Минимальный размер тега (8pt)
$max_real = 22; //--Максимальный размер тега (22pt)
Предположим, что результат выполненного SQL-запроса хранится в переменной ret. Далее необходимо определить минимальное и максимальное значение параметра cnt:
$min_db = 999999;
$max_db = 0;
foreach ($ret as $tag)
{
$min_db = min($min_db, $tag['cnt']);
$max_db = max($max_db, $tag['cnt']);
}
Для чего все это нужно? Допустим, в результате выполнения запроса мы получили пять самых популярных тегов с параметрами cnt (значениями популярности) соответственно: 500, 170, 40, 111, 22. Нам необходимо отобразить эти теги шрифтом размером от 8 (min_real) до 22 (max_real). Мы определили максимальное (max_db = 500) и минимальное (min_db = 22) значения популярности. Для определения размера шрифта, которым необходимо отобразить тег со значением популярности cnt воспользуемся формулой:
(cnt - min_db) / (max_db - min_db) * (max_real - min_real) + min_real
В общем, сплошная математика. Даже она иногда пригождается в сайтостроении.
Код построения облака тегов, в итоге, может выглядеть примерно так:
$tagsarr = array();
foreach ($ret as $tag)
{
$tagsarr[] = sprintf('<a style="font-size: %dpt;" title="%d" href="/articles/?tag=%s">%s</a>',
$min_db == $max_db ? $min_real : ( ($tag['cnt'] - $min_db) / ($max_db - $min_db) * ($max_real - $min_real) + $min_real ),
$tag['cnt'],
$tag['alias'],
$tag['title']
);
}
echo implode(', ', $tagsarr);
Участок
$min_db == $max_db ? $min_real : ...
описывает частный случай, когда максимальное и минимальное значение популярности равны, то есть все теги имеют одинаковую популярность. В этом случае отображаем их минимальным размером шрифта. Удачного кодинга!