]]>
ваш баннер
]]>

Как создать облако тегов для своего сайта на PHP

7 мая, 2008

Создание облака тегов
В этой статье я расскажу и, естественно, покажу пример создания облака тегов для сайта (блога). Основные инструменты – PHP и фреймворк CodeIgniter (подойдет любой другой).

Но, прежде всего, хочу поблагодарить Delchyve за идею.

Итак, переходим к делу.

Вы, конечно, знаете, что облако тегов используется на многих сайтах (в основном это блоги) как элемент навигации. По-сути, облако тегов – это набор ссылок с ключевыми словами, рядом с которыми обычно пишут количество постов, которые относятся к данному тегу.

Чтобы сфокусировать внимание посетителя на наиболее актуальных темах, размер шрифта тегов в облаке меняют в зависимости от количества постов, которые к нему относятся.

Если ваш сайт (блог) использует какую-нибудь CMS, например, WordPress, Joomla и т.п., то вы без труда найдете плагины, которые сами создадут облако тегов на основе ваших данных, а вам останется только разместить его в шаблоне сайта.

Но мы рассмотрим ситуацию, когда сайт пишется «с нуля» и вам нужно сформировать облако ручками :-) .

Прежде всего, вы должны четко понимать, что данные для создания облака мы получаем из базы данных, а способ их получения зависит от ее структуры (взаимосвязей между таблицами).

В качестве примера попробуем сформировать фрагмент такой базы данных для блога.

Мы хотим, чтобы пользователь мог присваивать любое количество тегов любому из постов. При этом один и тот же тег может быть присвоен нескольким постам. В принципе, можно разместить все эти данные внутри одной таблицы, т.е. сделать поле, в котором будут перечислены все теги через запятую. Но такой подход имеет несколько очень существенных недостатков.

Во-первых, информация в таблице будет дублироваться (если один и тот же тег присвоен нескольким постам).
Во-вторых, для поиска придется использовать предложение LIKE, а это очень неэффективно с точки зрения производительности.
В-третьих, простая операция вывода списка тегов потребует ряд дополнительных операций (разбивку строк на лексемы, формирования массива с тегами и т.д.).

Поэтому гораздо удобнее хранить посты и теги в разных таблицах.

Допустим, наша таблица с постами (назовем ее posts) содержит такие поля:

1) id – первичный ключ;
2) title – заголовок;
3) text – текст поста;
4) date – дата;
и др.

А таблица с тегами (tags):

1) id – первичный ключ;
2) tag – имя тега.

Теперь нужно связать таблицы между собой. Т.к. в данном случае мы имеем отношение «многие-ко-многим» (один пост и тот же пост может иметь несколько тегов, а один и тот же тег можно присвоить нескольким постам), то для его реализации нам потребуется еще одна таблица. Она будет называться posts_tags и иметь следующие поля:

1) id – первичный ключ;
2) postid – внешний ключ (связывает запись с таблицей posts);
3) tagid – внешний ключ (связывает запись с таблицей tags).

Каждая запись в таблице posts_tags определяет одну взаимосвязь между таблицами posts и tags.

На рисунке изображены связи между таблицами

Структура базы данных

Рассмотрим, как она заполняется.

Допустим в таблицах posts и tags уже есть какие-то данные.

posts

id text title date
1 post 1 title 1 2008-05-01 19:40:08
2 post 2 title 2 2008-05-01 19:40:39
3 post 3 title 3 2008-05-01 19:41:08

tags

id tag
1 php
2 html
3 java
4 ajax
5 JavaScript

Чтобы присвоить тег html второму посту (post 2), то в таблице posts_tags нужно создать запись:

postid = 2
tagid = 2

Хотим к этому же посту добавить еще тег JavaScript? Не проблема. Добавляем в posts_tags еще одну запись:

postid = 2
tagid = 5

Таким образом, используя эту таблицу, мы может создать любое количество взаимосвязей между постами и тегами.

Теперь переходим к реализации.

Как я и обещал, в качестве фреймворка мы будем использовать CodeIgniter. Но это совершенно не обязательно. Вы сможете легко переписать пример, используя только стандартные функции PHP.

Начнем с контроллера (main.php).

Code (php)
  1. class Main extends Controller {
  2.     function Main() {
  3.         parent::Controller();
  4.         $this->load->database();
  5.     }
  6.     function index() {
  7.         $this->load->model(‘tagcloudmodel’);
  8.         $pageData[‘tagcloud’] = $this->tagcloudmodel->getTagCloudData();
  9.  
  10.         $this->load->view(‘header’);
  11.         $this->load->view(‘tagcloud’, $pageData);
  12.         $this->load->view(‘footer’);
  13.     }
  14. }

Как видите, он имеет всего один метод – index(), который будет создавать страницу с облаком.

В конструкторе мы загрузили библиотеку для работы с базой данных (строка 4), а в начале метода index() – модель tagcloudmodel (о ней чуть позже).

После этого мы вызываем метод getTagCloudData() модели, который возвращает нам массив со всей информацией, необходимой для построения облака. И затем показываем страницу (строки 10-13).

Отдельно хочу отметить, что для отображения облака нам нужны.

1) Перечень всех тегов. Не проблема, просто читаем содержимое таблицы tags.

2) Количество постов, которым присвоен каждый тег. Тут чуть сложнее. Нужно посчитать сколько раз встречаются одинаковые цифры в поле tagsid (таблица posts_tags).

Теперь рассмотрим модель (tagcloudmodel.php)

Code (php)
  1. class TagCloudModel extends Model {
  2.     function TagCloudModel() {
  3.         parent::Model();
  4.     }
  5.  
  6.     function getTagCloudData() {
  7.         $qGetCloud = "SELECT tags.tag, COUNT(posts_tags.tagid) AS posts_count".
  8.                     " FROM posts_tags LEFT JOIN tags ON posts_tags.tagid=tags.id".
  9.                     " GROUP BY tags.id";
  10.         $res = $this->db->query($qGetCloud);
  11.         if ($res->num_rows() == 0) {
  12.             return false;
  13.         }
  14.         else {
  15.             return $res->result_array();
  16.         }
  17.     }
  18. }

Здесь тоже только один метод (не считая конструктора). В нем мы выполняем один запрос к базе данных и, если данные найдены, возвращаем массив с результатами.

Т.к. запрос выполняет основную часть работы, рассмотрим его подробнее. Условно запрос можно разбить на три части.

1) После предложения SELECT мы указываем, какие данные хотим получить (строка 7). Это имя тега и количество постов, которым он присвоен. (Для подсчета постов используем агрегатную функцию COUNT).

2) Указываем, из каких таблиц брать данные. Здесь мы используем «левое объединение» таблицы posts_tags с таблицей tags, а в условии объединения указываем, что posts_tags.tagid должен быть равен tags.id. Таким образом, MySQL для каждой записи в таблице posts_tags найдет соответствующую запись в таблице tags и подставит соответствующее имя тега.

3) Группируем поля по первичному ключу тега (строка 9). После этой операции в результирующем массиве теги повторяться не будут, а функция COUNT подсчитает, сколько раз встретился каждый тег.

Примечание. Этот запрос вернет только те теги, которые присвоены хотя бы одному посту (т.е. существует запись в таблице posts_tags). Если по каким-то причинам вам нужно вывести все теги (включая те, для которых нет постов), измените порядок объединения таблиц в запросе: .....FROM tags LEFT JOIN posts_tags ON........

Данные мы получили, переходим к созданию представлений.

Для этого примера я сделал 3 представления (заголовок, хвостовик и основная часть). Наверное, это перебор :-) , но для реальных сайтов заголовок и хвостовик обычно повторяются для нескольких страниц, поэтому лучше их сразу отделить.

В заголовке и хвостовике ничего особенного нет, поэтому я только приведу их код.

header.php

Code (html4strict)
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  4. <title>Облако тегов</title>
  5. </head>

footer.php

Code (html4strict)
  1. </body>
  2. </html>

А вот на основной части (tagcloud.php) остановимся подробнее.

Code (php)
  1. if ($tagcloud === FALSE) {
  2.     echo "Данные не найдены";
  3. }
  4. else {
  5.     $min = $tagcloud[0][‘posts_count’];
  6.     $max = $tagcloud[0][‘posts_count’];
  7.     for ($i = 1; $i < count($tagcloud); $i++) {
  8.         if ($tagcloud[$i][‘posts_count’] > $max) {
  9.             $max = $tagcloud[$i][‘posts_count’];
  10.         }
  11.         if ($tagcloud[$i][‘posts_count’] < $min) {
  12.             $min = $tagcloud[$i][‘posts_count’];
  13.         }
  14.     }
  15.     $minSize = 70;
  16.     $maxSize = 150;
  17.     foreach ($tagcloud as $item) {
  18.         if ($min == $max) {
  19.             $fontSize = round(($maxSize - $minSize) / 2 + $minSize);
  20.         }
  21.         else {
  22.             $fontSize = round((($item[‘posts_count’] - $min)/($max - $min)) * ($maxSize - $minSize) + $minSize);
  23.         }
  24.         echo "<span style=\"font-size:".$fontSize."%\">".$item[‘tag’]." (".$item[‘posts_count’].") </span>";
  25.     }
  26. }

Здесь мы проверяем, найдены ли данные (строки 1-3) и если найдены, начинаем формировать облако.

Прежде всего, находим теги, которые присвоены минимальному и максимальному количеству постов (строки 5-14).

После этого задаем минимальный и максимальный размер шрифта (в данном случае я задал 70% и 150%).

Теперь формируем цикл, который будет выводить теги (строки 17-26). Внутри цикла мы рассчитываем размер шрифта текущего тега (строки 18-23). Тег, для которого найдено минимальное число постов, будет иметь размер 70%, а тег с максимальным числом постов – 150%. Для остальных тегов будут рассчитаны промежуточные значения в зависимости от количества постов.

Результат показан на скриншоте.

Облако тегов

Естественно, для реального блога, каждый тег будет представлять собой ссылку, которая ведет на соответствующую страницу. Но это отдельная тема.

Как видите создать облако тегов совсем не сложно, задача, в общем-то, сводится к одному запросу.

Кстати, ради интереса посмотрите структуру базы данных WordPress. Думаю, вы легко найдете нужные таблицы.

Удачи!

Понравилась статья? Подпишитесь на продолжение rss link !

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в CodeIgniter, HTML, PHP, Web разработка

]]>

Комментарии (25)

Вы можете отслеживать обсуждение записи с помощью RSS 2.0 rss link

Вы также можете оставить комментарий, или трекбек с Вашего сайта.

  1. Delchyve 07.05.2008 в 11:02 (Ответить)

    Владимр, огромное спасибо за пост :)
    Внесли ясность.

  2. MAX 07.05.2008 в 18:08 (Ответить)

    Интересно. :) Я как раз на днях доделывал «свои» облака меток. Так что немного позанудствую. ;)

    В рамках статьи все сделано правильно, но вот с точки зрения конечного продукта, использование какой-то отдельной таблицы не совсем разумно. Метки - это частный случай любой другой информации для любой записи. В простонародье - это meta. У меня например используется такая структура (только часть полей, имеющее отношение в данному примеру):

    meta_id - id-мета автоинкремент
    meta_key - ключ, например ‘tags’
    meta_id_obj - id связанной таблицы, например номер записи
    meta_value - значение мета

    Таблица записей/страниц имеет:
    page_id - номер записи
    и т.д.

    То есть meta_key может быть чем угодно, например можно указать автора, источник, ключевые слова, описание, title страницы и т.д.

    При добавлении меток к записи в редакторе есть отдельное поле, где следует указать метки через запятую. При добавлении в базу эта строка разбивается на отдельные элементы и добавляется в таблицу meta. C одной стороны мы получаем дублирование меток в одной таблице, но при внимательном рассмотрении, всё равно придется хранить либо сами метки, либо какую-то связующую таблицу (в вашем случае posts_tags). В моем случае нет проблем с добавлениием одинаковых меток: удаляются старые, потом insert. В вашем же случае добавление несколько сложней, поскольку метка уже может существовать и нужно найти её id и связывать таблицы по этому номеру. У вас подход больше подходит не для меток, а для предопределенных рубрик, где их удобней не вводить вручную, а отмечать (checkbox). (У меня рубрики как раз по такому принципу и организованы. В WordPress также, только там это называется таксономией.)

    Для получения меток одной записи выполняется простой SQL:

    $CI->db->select('meta_value');
    $CI->db->where( array ( 'meta_key' => 'tags', 'meta_id_obj' => номер записи ) );
    $query = $CI->db->get('meta');

    Для получения массива всех меток в виде массива [метка] => колво:

    $CI->db->select('meta_value, COUNT(meta_value) AS meta_count');
    $CI->db->where( array ( 'meta_key' => 'tags' ) );
    $CI->db->join('page', 'page.page_id = meta.meta_id_obj' );
    $CI->db->group_by('meta_value');
    $query = $CI->db->get('meta');

    // переделаем к виду [метка] = кол-во
    if ($query->num_rows() > 0)
    {
    $tags = array();
    foreach ($query->result_array() as $row)
    $tags[$row['meta_value']] = $row['meta_count'];
    return $tags;
    }
    else return array();

    С таким массивом несколько проще работать при выводе: например конечная функция формирования облака получается такой:

    asort($tagcloud);
    $min = reset($tagcloud);
    $max = end($tagcloud);

    $minSize = 70;
    $maxSize = 150;
    $out = '';

    // здесь можно задать сортировку элементов
    arsort($tagcloud); // большие метки в начале

    foreach ($tagcloud as $tag => $count) {
    $fontSize = round((($count - $min)/($max - $min)) * ($maxSize - $minSize) + $minSize);
    $out .= "" . $tag . " (" . $count . ") ";
    }

    return $out;

    Вот примерно так. :)

    1. Владимир 08.05.2008 в 17:39 (Ответить)

      Да, читая такие комментарии начинаешь понимать смысл фразы user generated content :-)

      Если серьезно, мне ваш пример очень понравился. Полностью логичное продолжение темы.

      Но я тоже попридираюсь :-)

      В моем случае нет проблем с добавлением одинаковых меток: удаляются старые, потом insert.

      Этот момент я хочу уточнить.
      Например, есть метка:
      meta_id = 5
      meta_key = ‘tags’
      meta_id_obj = 4 (id поста которому присвоена данная метка)
      meta_value = ‘my_tag’
      Нужно добавить еще одну метку для этого поста. Для этого сначала удаляем все метки с meta_id_obj = 4, а затем вставляем новый список? Правильно?
      Если да, то нужна еще одна операция. Предварительно нужно получить список всех меток и добавить их в поле редактирования.

      всё равно придется хранить либо сами метки, либо какую-то связующую таблицу

      Да, но в связующей таблице поля имеют тип INT, а не VARCHAR, поэтому получаем выигрыш в размере базы.
      Кстати, я не очень удачно создал эту таблицу (posts_tags). Лучше сделать составной первичный ключ и не делать поля id вообще:
      PRIMARY KEY (postid, tagid)

      У вас подход больше подходит не для меток, а для предопределенных рубрик, где их удобней не вводить вручную, а отмечать (checkbox)

      Лично я очень часто когда добавляю закладки в memori.ru просто кликаю по существующим тегам чтобы не вводить их вручную, потому что можно легко ошибиться одним символом и получить две разные метки (тот же checkbox, вид сбоку :-) )

      asort($tagcloud);

      Сортировка вещь хорошая, но “кушает” ресурсов значительно больше чем просто поиск минимального и максимального значений. Хотя, обычно меток не много и врядли это заметно повлияет на общую производительность. Тем более если стоит задача выводить метки с максимальным количеством элементов первыми (тут без сортировки обойтись не получится, но можно выполнить ее в запросе к БД).

      1. MAX 08.05.2008 в 18:47 (Ответить)

        >> Например, есть метка: …
        >> Нужно добавить еще одну метку для этого поста. Для этого сначала удаляем все метки с meta_id_obj = 4, а затем вставляем новый список? Правильно?
        >> Если да, то нужна еще одна операция. Предварительно нужно получить список всех меток и добавить их в поле редактирования.

        Не совсем так. Получать существующие метки перед их обновлением (в бд) не нужно. В sql-запросе достаточно указать meta_key=tags и meta_id_obj=номер записи. Дальше delete(’meta’).

        То есть просто удаляются ВСЕ метки данной записи.

        Сам же процесс редактирования (юзером) может происходить по разному. У меня это просто отдельное поле, где через запятую выводятся все метки к данной записи. Поэтому юзер сразу видит все текущие метки этой записи и правит их как угодно. Когда он нажимает «Сохранить», метки передаются в виде строки. Перед insert строка разбивается в массив, обходя который и выполняется insert в базу.

        >> Да, но в связующей таблице поля имеют тип INT, а не VARCHAR, поэтому получаем выигрыш в размере базы.

        Абсолютно верно. Но все-таки метки не такие большие, поэтому разница в абсолютном выражении будет не велика. Просто на мой взгляд если речь идет именно о метках, то нельзя их приравнивать к предопределенным рубрикам, которые как раз и требуют связующей таблицы. meta более универсальна - именно это я пытаюсь донести. :)

        >> Лично я очень часто когда добавляю закладки в memori.ru просто кликаю по существующим тегам чтобы не вводить их вручную, потому что можно легко ошибиться одним символом и получить две разные метки (тот же checkbox, вид сбоку :-) )

        Признаться я не вижу разницы - можно сделать кликабельные существующие метки. Хоть чекбоксами. :)

        >> Сортировка вещь хорошая, но “кушает” ресурсов значительно больше чем просто поиск минимального и максимального значений.

        Честно говоря, первый раз про такое слышу. Почему-то мне всегда казалось, что «родные» функции PHP работают быстрей «самописных». ;)

        1. Владимир 09.05.2008 в 18:31 (Ответить)

          То есть просто удаляются ВСЕ метки данной записи.

          Значит если статья уже имеет 5 тегов и я хочу добавить еще 1, то сначала будут удалены 5 записей из БД, а затем вставлены новые 6? Выглядит немного неэкономно, но с другой стороны всего 2 запроса…

          нельзя их приравнивать к предопределенным рубрикам, которые как раз и требуют связующей таблицы. meta более универсальна

          Полностью согласен. Но что мешает использовать meta и связующую таблицу? Поле id в любом случае уникально. Связующая таблица может использоваться только для связи тегов (т.е. меток для которых meta_key=tags) с постами, а остальные meta будут использоваться без нее.
          Хотя, по-моему это все не принципиально, работать будут оба варианта. А чтобы сделать оптимизацию по скорости и потреблению ресурсов, нужно тестировать оба варианта в одинаковых условиях. Не знаю насколько это оправданно.

          «родные» функции PHP работают быстрей «самописных»

          Да, тут я погорячился :-) Хотя алгоритм сортировки в любом случае сложнее.

          1. MAX 09.05.2008 в 23:32 (Ответить) (Достигнут максимальный уровень вложенности комментариев)

            >> Но что мешает использовать meta и связующую таблицу? Поле id в любом случае уникально. Связующая таблица может использоваться только для связи тегов (т.е. меток для которых meta_key=tags) с постами, а остальные meta будут использоваться без нее.

            А зачем? Связующая таблица просто не нужна - ведь вполне достаточно одного запроса к одной таблице: в meta уже есть номер записи. ;)

            Кстати, когда-то у меня спрашивали как сделать два-три облака тэгов на WordPress. Вроде как одно для города, другое страны. В вашем случае задача опять сведется к ведению еще двух таблиц. В моем достаточно указать другой meta_key.

            Что касается производительности и ресурсоемкости, то тут вопрос сложный. Для себя я решил, что основной упор следует делать на кэширование. В этом случае функция может вообще не выполняться, а сразу вывести готовый результат из кэша. Например у меня облако меток сейчас целиком кэшируется.

            И еще по функции. Нужно добавить проверку, а то деление на ноль возможно (при выводе).

            if ($max == $min) $max++;

          2. Владимир 10.05.2008 в 08:53 (Ответить)

            В вашем случае задача опять сведется к ведению еще двух таблиц

            Не, еще две таблицы - это перебор. В такой ситуации я бы добавил еще одно поле в таблицу tags (posts_tags остается без изменений), т.е. структура стала бы очень похожа на ваш вариант :-) .
            Ну не нравится мне дублирование данных в таблице :-) .

            кеширование

            Да, пожалуй, от него и будет основной прирост производительности.

            if ($max == $min) $max++;

            Все время что-то забываю :oops: . Спасибо!

      2. Opanas 09.05.2008 в 15:56 (Ответить)

        Лучше индекс делать так PRIMARY KEY (tagid, postid)

        тогда будет использоваться индекс при поиске по tagid.

        А в остальном, спасибо за статью и комменты )

  3. Я у себя добавил в tags число тэгов отдельно как поле, что-бы не делать count каждый раз. Перерасчитывать надо при новой публикации или изменении тэгов.

    1. Владимир 08.05.2008 в 17:40 (Ответить)

      Тоже вариант, вообще с точки зрения оптимизации тут есть над чем поработать.

  4. aleXoid 09.05.2008 в 17:36 (Ответить)

    Это очень простой функционал тегов, но он вполне справляется со своей задачей. Практически такую же систему хранения я организовал для моего текущего проекта портала-магазина, где помимо прочего в таблице-аналоге “posts_tags” имеется еще два ключа:

    - Component (определяет к какому объекту был присвоен тэг: ‘news’, ‘goods’, ‘producers’, ‘blog’, ‘articles’)
    - ID_user - идентификатор пользователя. Возможно значение 0 - это когда суперадмин формирует теги, которые будут доступны всем новым пользователям по-умолчанию и помогает связывать контент.
    —-

    Немного в оффтоп, но не могу не задать вопрос, который может сэкономить мое время:

    Может быть кто-то наталкивался на готовое решение для CI, которое позволяло бы управлять блоками на сайте - всякие опросы, баннеры, меню ну и т.д. Т.е. чтобы глобально не прописывать нужные инструкции в каждом контроллере.

    Не поймите неправильно, я понимаю как это можно сделать :) Но может быть кто-то где-то натыкался на готовые решения. Буду признателен :)

    1. Владимир 09.05.2008 в 18:47 (Ответить)

      Может быть кто-то наталкивался на готовое решение для CI

      Честно говоря не сталкивался. Можно поискать на CIForge.
      А вообще этот функционал сильно напоминает CMS.

  5. Анфиса 09.05.2008 в 18:16 (Ответить)

    Так, а будет ли это облако тегов лучше чем обычный модуль для вордпресс? Будет ли он таким же функциональным, но более шустрым?

    1. aleXoid 09.05.2008 в 18:32 (Ответить)

      Анфиса,

      Это не модуль для WordPress, а отдельное решение для CodeIgniter :)

    2. Владимир 09.05.2008 в 18:51 (Ответить)

      Что бы этим решение было удобно использовать в WP его нужно переделать в виде плагина к WP и с учетом ее структуры базы данных.
      Т.е. в конечном итоге получится очередной плагин. Будет работать он быстрее или нет - зависит от вас :-)

  6. Сергей 20.05.2008 в 09:28 (Ответить)

    Надо на вордпрессе попробовать, а то никак для блога не могу норм прикрутить облако, сколько уже плагинов пробовал

  7. Sufir 04.06.2008 в 22:15 (Ответить)

    Хорошая статья, спасибо. Получил недавно задание сделать облако, а что это такое и не знал. Но у менятакой вопрос: А зачем оно собственно нужно, это облако? Я предполагал что это как-то в раскрутке помогает, хотя вряд ли так уж сильно. Или им действительно пользователи пользуются?

    1. Владимир 04.06.2008 в 23:00 (Ответить)

      Обычно облако используется вместо (или как дополнение) перечня разделов сайта. Часто в разделах информация группируется по темам сообщений, а в облаке - по ключевым словам, но по-большому счету это одно и то же.
      Пользователи пользуются :-) Зачастую в блогах это единственный способ навигации.
      В раскрутке оно помогает не больше чем любой другой навигационный блок.

      1. Sufir 05.06.2008 в 16:44 (Ответить)

        Спасибо, Владимир. Сам блогами не пользуюсь, поэтому как то не сталкивался. А когда обнаруживал подобное “облачко”, оно меня всегда несколько смущало. Теперь понятно. В общем на нормальном сайте с продуманной структурой это не особбенно нужно.

  8. Олег 06.06.2008 в 13:16 (Ответить)

    Спасибо за подробную статью. Поддержу позицию автора: дублирование записей в БД рекомендуется делать через дополнительную таблицу. Но соглашусь, что оба варианта будут работать.

    В статье описан случай хранения, частично вывода (с этим нет сложностей) и вывода облака.
    Есть встречный вопрос, как сделать так?
    http://www.google.com/webhp?complete=1&hl=en
    Такое применяется сейчас в социалке вконтакте.
    Т.е. чтобы при начале набора тега, появлялись варианты ответов.
    Но здесь тоже сложности. Через запятую внося ключевые слова, теоретически уже не получится показывать варианты существующих тегов.

    1. Владимир 06.06.2008 в 13:52 (Ответить)

      Есть видеоурок на эту тему http://video.derekallard.com/video/downloads

      И, честно говоря, я не до конца понял вопрос о тегах.
      Автодополнение реализуется с помощью ajax. Т.е. с помощью javascript анализируем введенный текст и отправляем запрос серверу, который должен вернуть список с вариантами. В простейшем случае можно сразу отправить весь введенный текст, но ничто не мешает сделать предварительную обработку, например, вырезать начало строки включая последнюю запятую. По-хорошему, конечно, нужно обеспечить подсказки не только для последнего тега. Т.е. определить положение курсора, вырезать текущий тег (по запятым) и отправить его серверу.

      Примерно такой вариант реализован на bobrdobr.ru, правда иногда подглючивает (или просто притормаживает).

      1. Олег 06.06.2008 в 16:42 (Ответить)

        пример:
        статья_1
        вводятся теги: яблоко, груша, слива, смородина

        статья_2
        вводятся теги: яблокИ, смородина, вишня, клубника

        как вносятся теги в табличку tags и как они разносятся в табличку posts_tags.
        что делать со смородиной? :)

        tags

        id tag
        1 яблоко
        2 груша
        3 слива
        4 смородина
        5 яблокИ
        6 смородина
        7 вишня
        8 клубника

        1. Владимир 06.06.2008 в 17:02 (Ответить)

          Смородина в таблице tags должна быть только одна.
          В таблице posts_tags будет две записи для смородины.
          Например,

          posts_tags

          id postid tagid
          1 5 4
          2 6 4

          где 5, 6 - id статьи 1 и статьи 2 в таблице posts.

          Естественно, перед добавлением тега нужно проверить существует ли он уже в базе.

  9. www.nu-ns.com.ua 10.06.2008 в 16:11 (Ответить)

    интересно, я но подошел когда прочтению к слову база сразу отпало интересное. Суть в чем. нужно сделать строчку скажем как мета тего ключевых слов в заголовке, после чего должен быть скрипт который беря данные с этой строчки, по-разному каждый раз, строил облако тегов. Зачем? Для поисковой оптимизации.

    1. Владимир 10.06.2008 в 20:11 (Ответить)

      По разному - это значит с разными якорями ссылок?
      Тогда ничего сложного, добавляем еще одну таблицу, в которой перечисляем варианты одного и того же тега. Получится что-то вроде:
      id - первичный ключ
      tagId - id основного тега в таблице tags
      altTagName - альтернативный тег

      После этого получаем все записи из этой таблицы, которые имеют один и тот же tagId, а затем выбираем случайным образом какой-то один.

Оставить комментарий

Введите ваш комментарий

* - обязательные для заполнения поля

Quicktags:

]]>