Статьи

Как использовать радио-кнопки с таксономиями

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

Это может создать проблему, если вы хотите убедиться, что для каждого сообщения можно выбрать только один термин. Конечно, вы могли бы подключиться к save_post и удалить любые «лишние» термины, но это не особенно удобно для пользователя и, конечно, не обеспечивает отличный пользовательский интерфейс. Иногда было бы более эстетически желательно представить свои таксономии по-другому. Эта статья покажет вам, как это сделать, и весь код, о котором мы говорим, должен быть добавлен в файл functions.php вашей темы. Мы сосредоточимся на переключателях, но вы можете использовать любой другой метод ввода, например, раскрывающееся меню.


WordPress автоматически создает метабокс таксономии, поэтому наша первая задача — удалить его, чтобы мы могли создать собственный вместо него. Я предполагаю, что название нашей таксономии — «mytaxonomy» (если вы хотите изменить метабокс тэгов или категорий WordPress, вы должны заменить его на «category» или «post_tag»).

Чтобы удалить метабокс, мы будем использовать remove_meta_box , который должен вызываться изнутри функции, подключенной к admin_menu . remove_meta_box принимает три аргумента.

  1. ID : это атрибут id, данный элементу div, содержащему метабокс. Обычно это «mytaxonomydiv» для иерархических таксономий или «tagsdiv-mytaxonomy» для неиерархических.
  2. Тип поста: тип поста, для которого отображается метабокс (например, «пост» или «страница» и т. Д.). Если ваш метабокс появляется для нескольких разных типов постов, вам нужно будет вызвать функцию remove_meta_box для каждого из них.
  3. Контекст : нормальный, расширенный или боковой.
1
2
3
4
add_action( ‘admin_menu’, ‘myprefix_remove_meta_box’);
function myprefix_remove_meta_box(){
   remove_meta_box(‘mytaxonomydiv’, ‘post’, ‘normal’);
}

Здесь мы подключаемся к меткому имени add_meta_boxes с помощью функции, которая добавит наш метабокс. Для этого функция вызовет add_meta_box который принимает довольно много аргументов, среди которых:

  1. ID : То же, что и выше, дать ему что-нибудь уникальное.
  2. Заголовок : заголовок метабокса.
  3. Обратный вызов : имя функции, которая будет производить внутренности нашего метабокса.
  4. Тип сообщения : То же, что и выше. Опять же, вам нужно будет вызывать эту функцию для каждого типа поста отдельно.
  5. Контекст : такой же, как указано выше.
  6. Приоритет : приоритет в контексте, где должны отображаться поля.
1
2
3
4
5
6
7
8
9
//Add new taxonomy meta box
 add_action( ‘add_meta_boxes’, ‘myprefix_add_meta_box’);
 function myprefix_add_meta_box() {
     add_meta_box( ‘mytaxonomy_id’, ‘My Radio Taxonomy’,’myprefix_mytaxonomy_metabox’,’post’ ,’side’,’core’);
 }
 
  function myprefix_mytaxonomy_metabox( $post ) {
     echo ‘This is my taxonomy metabox’;
  }

Вместе вышесказанное должно удалить метабокс по умолчанию и заменить его своим собственным, который в настоящее время ничего не делает, кроме отображения сообщения «Это мой метабокс таксономии». Следующим шагом является изменение функции обратного вызова для отображения того, что мы хотим.


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

Давайте пройдемся по нашей функции постепенно. Первый бит устанавливает некоторые переменные. Вам только нужно изменить переменную $taxonomy чтобы она соответствовала вашему названию таксономии. Обратите внимание также на переменную $name . Мы даем полям ввода имя tax_input[mytaxonomy] . Это имя для ввода внутри метабокса по умолчанию. Делая это, WordPress автоматически обрабатывает обновление термина таксономии поста.

1
2
3
4
5
6
7
8
9
//Set up the taxonomy object and get terms
$taxonomy = ‘mytaxonomy’;
$tax = get_taxonomy($taxonomy);//This is the taxonomy object
 
//The name of the form
$name = ‘tax_input[‘ .
 
//Get all the terms for this taxonomy
$terms = get_terms($taxonomy,array(‘hide_empty’ => 0));

Нам понадобится идентификатор текущего термина сообщения (мы ожидаем только один).

1
2
3
$postterms = get_the_terms( $post->ID,$taxonomy );
$current = ($postterms ? array_pop($postterms) : false);
$current = ($current ? $current->term_id : 0);

Если вы посмотрите на метабокс категории WordPress, вы увидите вкладку, в которой будут отображаться наиболее часто используемые термины. Чтобы воспроизвести это, нам понадобятся 10 самых популярных терминов. Мы снова используем функцию get_terms , но на этот раз get_terms не более 10 терминов и упорядочиваем их по количеству (количество постов с такой таксономией).

1
$popular = get_terms( $taxonomy, array( ‘orderby’ => ‘count’, ‘order’ => ‘DESC’, ‘number’ => 10, ‘hierarchical’ => false ) );

Далее мы хотим отобразить вкладки «Все категории» и «Наиболее часто используемые» (рекомендуется использовать метки таксономии везде, где это возможно). Если вы не хотите вкладок, вы можете просто удалить этот бит:

1
2
3
4
5
<!— Display tabs—>
<ul id=»<?php echo $taxonomy; ?>-tabs» class=»category-tabs»>
    <li class=»tabs»><a href=»#<?php echo $taxonomy; ?>-all» tabindex=»3″><?php echo $tax->labels->all_items;
    <li class=»hide-if-no-js»><a href=»#<?php echo $taxonomy; ?>-pop» tabindex=»3″><?php _e( ‘Most Used’ );
</ul>

Далее мы хотим установить, что отображать, когда мы находимся на вкладке «все категории»:

01
02
03
04
05
06
07
08
09
10
11
<!— Display taxonomy terms —>
<div id=»<?php echo $taxonomy; ?>-all» class=»tabs-panel»>
    <ul id=»<?php echo $taxonomy; ?>checklist» class=»list:<?php echo $taxonomy?> categorychecklist form-no-clear»>
        <?php foreach($terms as $term){
            $id = $taxonomy.’-‘.$term->term_id;
            echo «<li id=’$id’><label class=’selectit’>»;
            echo «<input type=’radio’ id=’in-$id’ name='{$name}’».checked($current,$term->term_id,false).»value=’$term->term_id’ />$term->name<br />»;
            echo «</label></li>»;
        }?>
    </ul>
</div>

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

Теперь мы делаем то же самое для вкладки «наиболее часто используемые»:

01
02
03
04
05
06
07
08
09
10
11
<!— Display popular taxonomy terms —>
<div id=»<?php echo $taxonomy; ?>-pop» class=»tabs-panel» style=»display: none;»>
    <ul id=»<?php echo $taxonomy; ?>checklist-pop» class=»categorychecklist form-no-clear» >
        <?php foreach($popular as $term){
            $id = ‘popular-‘.$taxonomy.’-‘.$term->term_id;
            echo «<li id=’$id’><label class=’selectit’>»;
            echo «<input type=’radio’ id=’in-$id’».checked($current,$term->term_id,false).»value=’$term->term_id’ />$term->name<br />»;
            echo «</label></li>»;
        }?>
    </ul>
</div>

Соберите это вместе, и наша полная функция

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//Callback to set up the metabox
function myprefix_mytaxonomy_metabox( $post ) {
    //Get taxonomy and terms
    $taxonomy = ‘mytaxonomy’;
 
    //Set up the taxonomy object and get terms
    $tax = get_taxonomy($taxonomy);
    $terms = get_terms($taxonomy,array(‘hide_empty’ => 0));
 
    //Name of the form
    $name = ‘tax_input[‘ .
 
    //Get current and popular terms
    $popular = get_terms( $taxonomy, array( ‘orderby’ => ‘count’, ‘order’ => ‘DESC’, ‘number’ => 10, ‘hierarchical’ => false ) );
    $postterms = get_the_terms( $post->ID,$taxonomy );
    $current = ($postterms ? array_pop($postterms) : false);
    $current = ($current ? $current->term_id : 0);
    ?>
 
    <div id=»taxonomy-<?php echo $taxonomy; ?>» class=»categorydiv»>
 
        <!— Display tabs—>
        <ul id=»<?php echo $taxonomy; ?>-tabs» class=»category-tabs»>
            <li class=»tabs»><a href=»#<?php echo $taxonomy; ?>-all» tabindex=»3″><?php echo $tax->labels->all_items;
            <li class=»hide-if-no-js»><a href=»#<?php echo $taxonomy; ?>-pop» tabindex=»3″><?php _e( ‘Most Used’ );
        </ul>
 
        <!— Display taxonomy terms —>
        <div id=»<?php echo $taxonomy; ?>-all» class=»tabs-panel»>
            <ul id=»<?php echo $taxonomy; ?>checklist» class=»list:<?php echo $taxonomy?> categorychecklist form-no-clear»>
                <?php foreach($terms as $term){
                    $id = $taxonomy.’-‘.$term->term_id;
                    echo «<li id=’$id’><label class=’selectit’>»;
                    echo «<input type=’radio’ id=’in-$id’ name='{$name}’».checked($current,$term->term_id,false).»value=’$term->term_id’ />$term->name<br />»;
                   echo «</label></li>»;
                }?>
           </ul>
        </div>
 
        <!— Display popular taxonomy terms —>
        <div id=»<?php echo $taxonomy; ?>-pop» class=»tabs-panel» style=»display: none;»>
            <ul id=»<?php echo $taxonomy; ?>checklist-pop» class=»categorychecklist form-no-clear» >
                <?php foreach($popular as $term){
                    $id = ‘popular-‘.$taxonomy.’-‘.$term->term_id;
                    echo «<li id=’$id’><label class=’selectit’>»;
                    echo «<input type=’radio’ id=’in-$id’».checked($current,$term->term_id,false).»value=’$term->term_id’ />$term->name<br />»;
                    echo «</label></li>»;
                }?>
           </ul>
       </div>
 
    </div>
    <?php
}

Я был осторожен в названии идентификаторов и переключателей в функции обратного вызова. Если вы попробуете все вышеперечисленное сейчас, вы обнаружите, что WordPress автоматически обрабатывает обновление почтовых терминов. Кроме того, JavaScript WordPress автоматически обрабатывает вкладку навигации. Есть один небольшой сбой. Переключатели «все категории» не синхронизированы с «наиболее часто используемыми». Если вы решили отказаться от вкладки «наиболее часто используемые», вы можете игнорировать этот раздел. В противном случае нам просто нужно добавить чуть-чуть JavaScript, чтобы исправить эту проблему.

Мы хотим добавить немного javascript на страницу, поэтому внутри нашей функции обратного вызова мы будем использовать ловушку, которая срабатывает при добавлении javascript в админку. То есть admin_enqueue_scripts . Поскольку мы добавляем нашу функцию в этот хук внутри нашей функции обратного вызова, она загружается только тогда, когда это необходимо. Просто добавьте эту строку вверху нашей функции обратного вызова:

1
add_action(‘admin_enqueue_scripts’,’myprefix_radiotax_javascript’);

Когда javascripts загружается на странице администратора, это вызовет нашу функцию. Эта функция ничего не делает, кроме как регистрирует и ставит в очередь наш javascript, который мы хотим загрузить в нижний колонтитул:

1
2
3
4
function myprefix_radiotax_javascript(){
    wp_register_script( ‘radiotax’, get_template_directory_uri() . ‘/js/radiotax.js’, array(‘jquery’), null, true );
    wp_enqueue_script( ‘radiotax’ );
}

Теперь для javascript, который нам действительно нужен, создайте файл в папке js вашей темы. Мы назовем его radiotax.js , и вот код, который нужно вставить внутрь:

1
2
3
4
5
6
7
8
jQuery(document).ready(function($) {
    var taxonomy = ‘mytaxonomy’;
    $(‘#’ + taxonomy + ‘checklist li :radio, #’ + taxonomy + ‘checklist-pop :radio’).live( ‘click’, function(){
        var t = $(this), c = t.is(‘:checked’), id = t.val();
        $(‘#’ + taxonomy + ‘checklist li :radio, #’ + taxonomy + ‘checklist-pop :radio’).prop(‘checked’,false);
        $(‘#in-‘ + taxonomy + ‘-‘ + id + ‘, #in-popular-‘ + taxonomy + ‘-‘ + id).prop( ‘checked’, c );
    });
});

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


И с этим мы закончили. WordPress обрабатывает все остальное для нас. Хотя есть возможности для улучшения … как насчет добавления новых терминов? Я пропустил это из нашего метабокса, потому что это невероятно сложно сделать. Это будет включать в себя гораздо больше JavaScript, а также немного действий на стороне сервера.


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