Облако тегов на PHP
Теги (ярлыки) — один из способов структурирования материала сайта. Веб-мастер при добавлении публикации на сайт присваивает ей несколько тегов — ключевых слов, которые позволяют понять ее тематику. Впоследствии на сайте возможен отбор и поиск материала по тегам.
Некоторые теги повторяются у различных статей, такие теги становятся популярными. На этом сайте, допустим, были бы популярны теги 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 : ...
описывает частный случай, когда максимальное и минимальное значение популярности равны, то есть все теги имеют одинаковую популярность. В этом случае отображаем их минимальным размером шрифта. Удачного кодинга!
Кстати, есть в планах внедрение облака тегов на MyFirstSite. В комментариях на странице о проекте уже подымался вопрос о недостаточно удобной системе навигации по сайту.
Я сделал по другому немного исключил промежуточную таблицу хранения посчитал их не нужными
cblock_tags таблица хранения тегов и к чему они принадлежат
id_element это id новости tag текстовое значения тега например "Союз" группировку сделал по названию тега
id_cblock_g это как бы сказать группа категории новостей
cblock_element это таблица новостей id_element инкремент таблицы
при добавлении тега вставляется текст через запятую который через JS разбивается крассива использовал jQuery TegInput унего есть также погрузка вариантов тегов через ajax
Неплохой подход, мне понравился. На этом сайте облако тегов на основе этого скрипта реализовано?
sadex, да, на нем.
Можно примеры базы данных самый минимум пожалуйста!
bermuda, ну я показал в статье примерную логическую структуру таблиц.
хорошо это уже неважно.
Вот я вывел список тегов допустим названия тегов
original-mix
remix
а адрес этих тегов
www.site.ru/tags/original-mix/
www.site.ru/tags/remix/
то есть получается так что в корне сайта должна быть папка tags в которой есть папки original-mix и remix и в каждой из них еще по файлу index.php так?
или лучше осуществить таким образом?
www.site.ru/index.php?tags=original-mix
www.site.ru/index.php?tags=remix
А, я понял. Нет, никакой папки tags не нужно, сами URL-адреса формируются при помощи механизмов, о которых можно почитать здесь:
http://www.myfirstsite.ru/qna/16
http://www.myfirstsite.ru/qna/2
спасибо буду разбираться
Неплохой подход, мне понравился