WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

Таксономии в WordPress

Что такое таксономии в WordPress? Кто не знает, и тем кто думает, что знает о таксономиях все, будет полезно прочитать эту статью. Я подробно разберу что скрывается под этим странным словом, что оно значит в WordPress и как таксономии устроены. Думаю, в этом разборе что-то полезное найдет каждый.

Читайте также, как устроенны записи в WordPress
Читайте также, как устроенны метаполя в WordPress

О таксономиях

Слово «Taxonomy» пришло к нам, как всегда, из греческого: taxis — расположение, nomos — закон, принцип. Т.е. Таксономия - это принцип расположения чего-либо. Для WordPress - это принцип расположения записей.

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

Структура контента в WordPress очень простая: контент состоит из записей и таксономий, которые связывают эти записи - по сути, это все! К контенту также относятся комментарии и файлы, но и то и другое является частью записи... Есть еще пользователи, но это как бы и не контент, а отдельная сущность. Вот и получается, что таксономии связывают только записи.

Стоит обратить внимание, что в WordPress «Таксономия» - это только название, т.е. таксономии как таковой не существует - есть только запись о её существовании. А что-то реальное в таксономии - это её элементы. Например, возьмем таксономию «Рубрики» (category) - это только название - запись в переменной PHP, а реальные данные таксономии - это созданные рубрики - её элементы. Например, если не создавать ни одной рубрики, то условно можно сказать, что таксономии нет (она пуста) - в базе данных она нигде не записана, а существует лишь в переменных PHP, где указано название таксономии и её свойства (опции), причем создается такая переменная налету во время генерации страницы. Записи привязываются именно к элементам таксономии, а не к самой таксономии. Так как записи связаны не с таксономией, а с её элементами, то и вся последующая работа с таксономией - это работа с её элементами.

Элементы таксономии называются terms. Для краткости так и будем их называть - термины.

меню

Типы таксономий

Выше я говорил, что при создании таксономии ей задаются свойства. Одно из самых важных свойств - это тип таксономии. Так, таксономии делятся на два типа:

  1. Древовидные - например рубрики

  2. Линейные (плоские) - например метки

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

Схематически это выглядит как-то так:

меню

Базовые таксономии WordPress

По умолчанию в WordPress существует пять таксономии:

  • category - рубрики

  • post_tag - метки

  • post_format - скрытая таксономия. Термины этой таксономии - это форматы записей.

  • nav_menu - скрытая таксономия. Термины этой таксономии - это созданные меню навигации, к ним прикрепляются записи (ссылки меню). Если в меню создается произвольная ссылка, то её данные помещаются в таблицу записей (wp_posts) с типом записи nav_menu_item, а запись прикрепляется к термину. Все опции ссылки (URL, анкор и т.д.) хранятся в метаполях записи. Тоже самое происходит, если в эту таксономию помещается элемент другой таксономии, например рубрика - также создается запись в таблице записей, а данные помещаются в метаполя записи. Система топорная и не очень практичная, зато независимая, хорошо расширяемая, а главное простая - в стиле WordPress.

  • link_category - разделы для ссылок, которые отключены в последних версиях. Подробнее о включении ссылок.
меню

Создание своих таксономий

Создается таксономия с помощью функции register_taxonomy() или соответствующего плагина, например, «Custom Post Type UI». При этом, как я уже говорил, в базу данных ничего не добавляется, а создается только описание таксономии и её свойств в глобальной переменной PHP и в правилах ЧПУ. Как только был создан хоть один элемент таксономии, в БД появляется запись о новом термине, а к нему уже можно прикрепить запись.

При создании таксономии, ей можно указать самые разные свойства (опции), например:

  • тип: древовидная или плоская.

  • тип записи для которой создается такса, тогда при редактировании записи в админке появится блок, где можно добавить запись в таксономию (связать запись с термином). Например таким блоком является блок рубрик при редактировании записи.

  • как будет выглядеть ссылка на элемент таксономии. Эта «хрень» называется ЧПУ (человеко-понятный УРЛ).

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

  • другие параметры... Полный список смотрите в описании функции register_taxonomy().

Почему нужно создавать произвольные таксономии?

Если везде использовать Рубрики, то довольно быстро ваш код превратиться в кашу. В результате расширять функционал сайта будет все сложнее, а скорость работы будет все медленнее.

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

В этом случае, новые таксономии в разы все упростят. Если у нас будут отдельные таксономии для каждой группы свойств, например: sale_price, number_of_bedrooms, location, то у нас появятся отдельные блоки при редактировании дома, в которых удобнее сориентироваться и выбрать куда что разместить, а также, можно будет создавать отдельные запросы по каждому типу свойства. Все это будет иметь отдельные названия, что упростит написание, понимание и скорость запросов.

Так может выглядеть запрос, когда нужно получить дешевые дома в Воронеже:

$houses = get_posts( array(
	 'posts_per_page' => 8,
	 'orderby'        => 'rand',
	 'post_type'      => 'houses',
	 'sale_price'     => 'cheap',
	 'location'       => 'voronej'
) );

А если тоже самое сделать с рубриками, то код получится больше, будет менее понятный и быстрый.

Создавать новые таксы - это часто удобно и выгодно, в конечном счете.

меню

Структура: таблицы таксономий в БД

В базе данных WordPress за таксономии отвечают, не много не мало, четыре таблицы. Разберем каждую.

wp_terms

Содержит элементы таксономии (термины) и базовую информацию о них. Это основная таблица элементов таксономии. Зависит от таблицы wp_term_taxonomy - они всегда идут в связке.

term_id
Уникальный ID термина (ID строки таблицы).
name
Название термина, пр: «Авторские функции».
slug
Ярлык (слаг) термина, пр: «avtorskie-funkcii».
term_group
Устарелое поле, больше не используется.

wp_term_taxonomy

Cодержит дополнительные данные об элементе таксономии, в частности важные из них - это к какой таксономии относится термин (поле taxonomy) и с какой записью связан (поле term_taxonomy_id).

term_taxonomy_id
ID строки в этой таблице, связывается с полем term_taxonomy_id из wp_term_relationships.
term_id
ID термина. Связывается с полем term_id из wp_terms.
taxonomy
название таксономии, к которой относится термин.
description
описание для термина.
parent
содержит ID родительского термина (для древовидных такс.).
count
содержит количество записей в термине.

Если устанавливается WP 4.4 или выше, то в БД будет одна запись в wp_term_taxonomy для каждого термина в wp_terms, а это значит что значения полей term_taxonomy_id и term_id всегда будут одинаковые. Но если вы создавали сайт на версии ниже 4.4, то может быть несколько записей для одного термина. Такое происходило, когда создавался термин, но в другой таксономии уже был термин с таким же названием и ярлыком. В этом случае новый термин в wp_terms не создавался, а вместо этого создавалась новая запись в wp_term_taxonomy, которая означала что тот термин принадлежит к еще одной таксономии. Именно для таких «мультитерминов» нужны дополнительные поля: description, parent и count, чтобы они отличались для одного термина и его разных таксономий.

А с версии WP 4.4, каждый термин имеет свой уникальный ID, и даже при совпадении названия и ярлыка терминов из разных таксах, создаются одинаковые записи в таблице wp_terms. Такой подход в разы понятнее и проще, при этом минусов почти нет. Сразу так сделать не догадались... Впрочем до версии WP 2.3 логика таксономий была еще хуже...

Сегодня старая логика еще поддерживается и это означает, что нужно учитывать что одна запись в wp_terms, может иметь несколько записей в wp_term_taxonomy.

Технически таблица wp_term_taxonomy не нужна с версии 4.4, потому что логика хранения данных изменилась и по новой логике поля taxonomy, description, parent, и count можно поместить в таблицу wp_terms и переписать весь связанный код движка и всех плагинов... Но все это совсем не просто, учитывая полную обратную совместимость WordPress (привет тем, кто не любит обновляться). Поэтому пока наслаждаться новой логикой в полной мере невозможно.

При обновлении до версии WP 4.2 сдвоенные термины были разделены и теперь данные о разделении находятся в опции get_option('_split_terms'), подробнее об этом читайте в описании функции wp_get_split_terms().

К слову, на этом сайте таких сдвоенных терминов оказалось всего 12 из нескольких сотен существующих, что еще раз доказывает несостоятельность прежней логики такс (было столько разветвлений в коде и всяких JOIN в sql запросах, только для того, чтобы не писать 12 строк в таблицу БД).

меню

wp_term_relationships

Содержит связи терминов с записями. Таблица показывает какая запись какому термину принадлежит. Только ID термина тут связывается через поле term_taxonomy_id, почему именно такая непонятная связь, описано выше: в таблице wp_term_taxonomy.

Эта таблица содержит всего три поля:

object_id
Содержит ID записи (значение поля ID из таблицы wp_posts). Если включена поддержка ссылок, то также будет содержать ID ссылки из таблицы wp_links.
term_taxonomy_id
Содержит значение такого же поля из таблицы wp_term_taxonomy.
term_order

Содержит порядок в котором были указаны термины, при прикреплении их к записи. Например, при редактировании записи мы указали ей 2 рубрики и 3 метки, вот в каком порядке мы их видим (они передались в POST запросе), такие значения сюда будут записаны: 1, 2 для рубрик, и 1, 2, 3 для меток.

По умолчанию эта функция отключена для всех встроенных таксономий (поле содержит 0). Чтобы её включить, нужно указать параметр sort при регистрации таксономии, см. register_taxonomy().

меню

wp_termmeta

Содержит метаданные терминов. Эта таблица дополняет таблицу wp_terms.

В wp_termmeta принято сохранять любые дополнительные данные термина, например это могут быть СЕО поля: заголовок, описание и что угодно еще.

Структуру таблица имеет такую же, как и другие таблицы метаданных: wp_postmeta, wp_commentmeta, wp_usermeta. Логика хранения, кэширования и получения метаданных WP едина для всех типов метаданных: посты, таксы, комменты, юзеры (об этом написал отдельную статью).

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

meta_id
ID метаполя. Обычно нигде не используется...
term_id
ID термина из таблицы wp_terms.
meta_key
Ключ метаполя.
meta_value
Значение метаполя. Всегда строка, т.е. числа хранятся как строки, а массивы в сериализованном виде.

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

меню

Связь всех таблиц

Для создания своих SQL запросов, когда базовые функции не справляются или справляются не так как хотелось бы, нужно знать как таблицы связываются.

Давайте посмотрим SQL запрос, который свяжет все таблицы с помощью JOIN. Запрос ниже вернет все записи типа post и данные к какому термину прикреплена каждая запись:

SELECT t.name, t.term_id, tt.taxonomy, p.ID, p.post_title, p.post_date 
FROM wp_terms t
	INNER JOIN wp_term_taxonomy tt ON (t.term_id = tt.term_id)
	INNER JOIN wp_term_relationships tr ON (tt.term_taxonomy_id = tr.term_taxonomy_id)
	INNER JOIN wp_posts p ON (tr.object_id = p.ID)
WHERE p.post_type = 'post'

Получим:

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

-

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

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

17 комментов
Полезные 1 Вопросы 5 Все
  • Ilya demily.ru

    Это лучшее, что я читал про taxonomy smile

    22
    Ответить2.2 года назад #
    • @ Инга yurpraktika.ru

      Этот парень вообще-всё лучшее, что есть в инете про вордпресс. И видимо очень хорошо воспитан. Уважает своих читателей не тратя их время good на бесполезные переливания из пустого в порожнее.

      19
      Ответить1.4 года назад #
  • @ Андрей

    Подскажите, можно ли для произвольной таксономии изменить метабокс на экране редактирования поста?

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

    1
    Ответить2.2 года назад #
    • Kama7631

      Можно. В register_taxonomy() укажи название нужной функции в параметре meta_box_cb. См. описание там все есть.

      Но там были какие-то подводные камешки, не помню что именно...

      Ответить2.2 года назад #
      • @ Андрей

        Круто! Спасибо.

        Ответить2.2 года назад #
      • @ Андрей

        Нашлись камушки. smile

        К посту не привязываются термины иерархической таксы, выбранные в "плоском" метабоксе.

        Поиск - норм, кнопка "Добавить" - норм, но после сохранения - ни одного термина.

        В быстром редактировании такса отображается списком терминов с чекбоксами и отсюда термины привязываются нормально.

        2
        Ответить2.2 года назад #
  • Есть ли какое нибудь решения для выборки таксономии, которая пересекается с другой таксономией в записях.
    Пример
    есть таксономия size
    и таксономия type
    и записи product
    Вывести текущие размеры(size) товаров(product) типа обувь(type->term_id = 2).
    Буду очень благодарен за ответ)

    Ответить2 года назад #
  • такой вопрос, я использую тему jannah в ней есть разные сетки masonry и другие сетки, я зарегистрировал новую таксономию, подскажите как сделать чтоб сетки можно было в новой таксономии добавлять? или придется все файлы сетки переписывать так как они запилины под category?

    Ответить1.1 года назад #
  • Иоанн

    Чтобы текст можно было читать и не корёжиться, автору нужно перед публикацией вставлять в текстовый редактор и нажимать F7, чтобы вычищать совсем уж элементарные ошибки уровня средней школы.

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

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

    Ответить11 мес назад #
    • Kama7631

      Как умею так пишу, по возможности проверяю. pardon

      4
      Ответить11 мес назад #
  • @ Umed

    Здравствуйте.
    Как известно, в термах плоских таксономий, невозможно в описание вписать код, и транслировать. После сохранения, код срезается, и остаётся только текст.
    А возможно-ли, в произвольную таксономию, добавить контейнер, для добавления иконки (а лучше фотографий), с выводом на странице термы ?

    Ответить10 мес назад #
  • Насколько плохо, когда одна запись принадлежит нескольким рубрикам, если в будущем я планирую сделать фильтр-поиск, где записи нужно находить по принципу "И" и "ИЛИ"? То есть, чтобы выполнялось условие, что запись должна одновременно находится в рубрике "Сахар" и "Кариес".

    При этом гипотетически у меня 300 рубрик с вложенностью до 12, на каждую рубрику приходится по 1000 материалов, и одновременно, 1 материал может принадлежать 2-4 рубрикам.

    Прежде всего интересует вопрос скорости чтения с БД, чтобы посетитель максимально быстро получал страницу.

    За материал спасибо. Правда уснул на половине, потому что плохо разбираюсь в теме. Но вернусь в другой день и дочитаю.

    Ответить10 мес назад #
  • Подскажите, возможно ли сделать иерархию в метках?
    Пример:
    Метка: Цвет (сайт.ру/тег/цвет/)
    Метка: - красный (сайт.ру/тег/цвет/красный)
    Метка: - синий (сайт.ру/тег/цвет/синий)

    Нашел ответ, на данный вопрос, через рубрики: тут

    Ответить8 мес назад #
    • Kama7631

      Для этого создай новую таксономию и сделай её древовидной...

      Ответить8 мес назад #
  • как реализованы "атрибуты" на woocommerce? /wp-admin/edit.php?post_type=product&page=product_attributes

    Ответить5 мес назад #
  • @ Олег

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

    Ответить5 мес назад #
Здравствуйте, !     Войти . Зарегистрироваться