Добавление термина в произвольную таксономию

6 окт. 2014 г., 05:38:42
Просмотры: 29.3K
Голосов: 10

Создал пользовательскую таксономию для управления макетом отдельных записей, по сути нужно добавить два варианта - Макет 1 и Макет 2.

// Регистрация пользовательской таксономии
function custom_taxonomy() {

    $labels = array(
        'name'                       => _x( 'Макет', 'Название таксономии', 'text_domain' ),
        'singular_name'              => _x( 'Макет', 'Название таксономии в единственном числе', 'text_domain' ),
        'menu_name'                  => __( 'Таксономия', 'text_domain' ),
        'all_items'                  => __( 'Все элементы', 'text_domain' ),
        'parent_item'                => __( 'Родительский элемент', 'text_domain' ),
        'parent_item_colon'          => __( 'Родительский элемент:', 'text_domain' ),
        'new_item_name'              => __( 'Название нового элемента', 'text_domain' ),
        'add_new_item'               => __( 'Добавить новый элемент', 'text_domain' ),
        'edit_item'                  => __( 'Редактировать элемент', 'text_domain' ),
        'update_item'                => __( 'Обновить элемент', 'text_domain' ),
        'separate_items_with_commas' => __( 'Разделяйте элементы запятыми', 'text_domain' ),
        'search_items'               => __( 'Поиск элементов', 'text_domain' ),
        'add_or_remove_items'        => __( 'Добавить или удалить элементы', 'text_domain' ),
        'choose_from_most_used'      => __( 'Выбрать из часто используемых', 'text_domain' ),
        'not_found'                  => __( 'Не найдено', 'text_domain' ),
    );
    $capabilities = array(
        'manage_terms' => 'foobar',
        'edit_terms'   => 'foobar',
        'delete_terms' => 'foobar',
        'assign_terms' => 'foobar' 
    );
    $args = array(
        'labels'                     => $labels,
        'hierarchical'               => true,
        'public'                     => true,
        'show_ui'                    => true,
        'show_admin_column'          => false,
        'show_in_nav_menus'          => false,
        'show_tagcloud'              => false,
        'capabilities'               => $capabilities,
    );
    register_taxonomy( 'Layout', array( 'post' ), $args );

}

// Хук в действие 'init'
add_action( 'init', 'custom_taxonomy', 0 );

Параметры capabilities установлены в недопустимые значения, чтобы предотвратить редактирование терминов, но я не могу заставить работать wp_insert_term.

Добавление двух терминов в мою пользовательскую таксономию не должно быть таким сложным, верно?

Использование этого кода для вставки термина не работает, хотя если изменить название пользовательской таксономии на 'category' (стандартную WP), всё работает нормально. В чем проблема?

function example_insert_category() {
    $parent_term = term_exists( 'layout' ); // возвращается массив, если указана таксономия
    $parent_term_id = $parent_term['term_id']; // получаем числовой ID термина
    wp_insert_term(
        'Пример категории',
        'layout',
        array(
          'description' => 'Это пример категории, созданной с помощью wp_insert_term.',
          'slug'        => 'example-category'
        )
    );
}
add_action( 'after_setup_theme', 'example_insert_category' );
1
Комментарии

Как и обещал, я выложил код плагина. Надеюсь, это поможет :-)

Pieter Goosen Pieter Goosen
7 окт. 2014 г. 19:03:28
Все ответы на вопрос 1
8
13

РЕДАКТИРОВАНИЕ 2

Как и обещал, вот код плагина.

Известно, что пользовательские таксономии и типы записей следует помещать в плагин, а не в тему. Я убрал некоторые части из своего плагина.

КАК ЭТО РАБОТАЕТ

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

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

Для этого нужно подключить функцию к хуку register_activation_hook. Этот хук срабатывает один раз — при активации плагина, он не будет повторяться при обновлении страницы. Единственный раз, когда он сработает снова, — это когда плагин будет деактивирован и активирован повторно.

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

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

Вот код плагина:

<?php
/**
Plugin Name: Создание терминов
Plugin URI: http://wordpress.stackexchange.com/q/163541/31545
Description: Создание терминов
Version: 1.0
Author: Pieter Goosen
License: GPLv2 or later
*/
class Test_Terms {

    function __construct() {
        register_activation_hook( __FILE__, array( $this, 'activate' ) );
        add_action( 'init', array( $this, 'create_cpts_and_taxonomies' ) );
    } 

    function activate() {
        $this->create_cpts_and_taxonomies();
        $this->register_new_terms();
    }

    function create_cpts_and_taxonomies() {

        $args = array( 
            'hierarchical'                      => true,  
            'labels' => array(
                'name'                          => _x('Тестовая таксономия', 'taxonomy general name' ),
                'singular_name'                 => _x('Тестовая таксономия', 'taxonomy singular name'),
                'search_items'                  => __('Поиск тестовой таксономии'),
                'popular_items'                 => __('Популярные тестовые таксономии'),
                'all_items'                     => __('Все тестовые таксономии'),
                'edit_item'                     => __('Редактировать тестовую таксономию'),
                'edit_item'                     => __('Редактировать тестовую таксономию'),
                'update_item'                   => __('Обновить тестовую таксономию'),
                'add_new_item'                  => __('Добавить новую тестовую таксономию'),
                'new_item_name'                 => __('Новое название тестовой таксономии'),
                'separate_items_with_commas'    => __('Разделить тестовые таксономии запятыми'),
                'add_or_remove_items'           => __('Добавить или удалить тестовые таксономии'),
                'choose_from_most_used'         => __('Выбрать из наиболее используемых тестовых таксономий')
            ),  
            'query_var'                         => true,  
            'rewrite'                           => array('slug' =>'test-tax')        
        );
        register_taxonomy( 'test_tax', array( 'post' ), $args );
    }

    function register_new_terms() {
        $this->taxonomy = 'test_tax';
        $this->terms = array (
            '0' => array (
                'name'          => 'Тест 1',
                'slug'          => 'test-1',
                'description'   => 'Это тестовый термин 1',
            ),
            '1' => array (
                'name'          => 'Тест 2',
                'slug'          => 'test-2',
                'description'   => 'Это тестовый термин 2',
            ),
        );  

        foreach ( $this->terms as $term_key=>$term) {
                wp_insert_term(
                    $term['name'],
                    $this->taxonomy, 
                    array(
                        'description'   => $term['description'],
                        'slug'          => $term['slug'],
                    )
                );
            unset( $term ); 
        }

    }
}
$Test_Terms = new Test_Terms();

РЕДАКТИРОВАНИЕ 1

Ваша проблема с вставкой терминов связана с хуком. after_setup_theme выполняется до init, что означает, что вы пытаетесь вставить термин в ещё не зарегистрированную таксономию.

Я бы рекомендовал переместить функцию wp_insert_term внутрь вашей функции init, сразу после register_taxonomy.

Также желательно сначала проверить, существует ли термин (term_exists), прежде чем вставлять его.

Пример:

// Регистрация пользовательской таксономии
function custom_taxonomy() {

   //КОД ДЛЯ РЕГИСТРАЦИИ ТАКСОНОМИИ

   if( !term_exists( 'Пример категории', 'layout' ) ) {
       wp_insert_term(
           'Пример категории',
           'layout',
           array(
             'description' => 'Это пример категории, созданной с помощью wp_insert_term.',
             'slug'        => 'primer-categorii'
           )
       );
   }
}

// Подключение к хуку 'init'
add_action( 'init', 'custom_taxonomy', 0 );

Обратите внимание, код не тестировался

ИСХОДНЫЙ ОТВЕТ

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

Вот руководство по выбору имён для пользовательских таксономий (и пользовательских типов записей):

  1. Следующее не допускается в именах пользовательских таксономий и пользовательских типов записей:

    • Заглавные буквы или camelCase

    • Любые специальные символы, кроме подчёркиваний (_)

    • Пробелы

    • Более 32 символов для таксономий и 20 для типов записей

    • Любые зарезервированные имена, и обратите внимание, это касается любых пользовательских соглашений об именах, а не только имён таксономий.

  2. Если в имени таксономии больше одного слова, они должны разделяться подчёркиваниями, а не дефисами (-). Мне возражали, что дефисы лучше для SEO в URL-адресах таксономий. Это правда, поэтому существуют правила перезаписи для корректировки URL. Никогда не изменяйте имена таксономий или типов записей ради SEO URL.

Также стоит убрать странные возможности. Это тоже может создать проблему.

Если это не решит вашу проблему, пожалуйста, добавьте код, который вы используете с wp_insert_term.

Ссылки:

6 окт. 2014 г. 07:35:25
Комментарии

Изучив исходный код, я немного озадачен, потому что параметр $taxonomy вообще не проходит санитаризацию, если аргумент query_var установлен в true. Это, честно говоря, довольно невероятно. В остальных случаях он санируется с помощью sanitize_title_with_dashes(), которая, как следует из названия, заменяет символы на дефисы повсюду. Что тоже удивительно, так как их использование не рекомендуется.

Nicolai Grossherr Nicolai Grossherr
6 окт. 2014 г. 21:23:17

Кроме того, вы можете свободно использовать цифры где угодно, в том числе в начале, хотя повсюду указано, что этого делать не стоит. Однако я не смог найти однозначного объяснения, почему цифры нежелательны. В отличие от дефисов, где хотя бы есть предупреждение: »Кроме того, если тип записи содержит дефисы, вы не сможете добавить колонки на страницу администрирования этого типа записей (используя действие 'manage_<Имя пользовательского типа записи>_posts_columns')« на странице кодекса для register_post_type().

Nicolai Grossherr Nicolai Grossherr
6 окт. 2014 г. 21:24:12

Хотя это и спрятано в разделе »Зарезервированные типы записей«. Я не понимаю, почему такие потенциально (или точно) проблемные вещи не контролируются жёстче. Иначе это просто напрашивается на неприятности без веской причины.

Nicolai Grossherr Nicolai Grossherr
6 окт. 2014 г. 21:25:55

Должен согласиться, у WordPress есть свои недостатки. Некоторые просто криминальны :-). Думаю, дефисы — одна из самых обсуждаемых тем, и они же чаще всего используются в названиях. Их провал становится очевидным, когда начинаешь разбираться в иерархии шаблонов. Создайте таксономию из двух слов, разделенных дефисом, например my-taxonomy, и попробуйте создать шаблон таксономии taxonomy-my-taxonomy.php — увидите провал. Где-то читал про проблему с цифрами, нужно перепроверить. Это мой список безопасных практик, которым я следую, и он работает идеально. Спасибо за информацию, ценю это.

Pieter Goosen Pieter Goosen
6 окт. 2014 г. 21:41:17

Я тоже, но только потому, что с самого начала учился делать правильно. Большую часть знаний я получил на [wordpress.se] от умных и опытных людей. Поэтому многих ошибок я просто не совершал.

Nicolai Grossherr Nicolai Grossherr
6 окт. 2014 г. 21:48:04

Всегда пожалуйста. Наслаждайтесь :-)

Pieter Goosen Pieter Goosen
7 окт. 2014 г. 20:39:57

По моему мнению, этот ответ следует защитить. Подробности в этом ответе/примере очень важны, и они недостаточно часто упоминаются в Codex.

Charles Charles
22 нояб. 2015 г. 18:15:33

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

Anders Östman Anders Östman
20 мар. 2017 г. 11:45:21
Показать остальные 3 комментариев