Метабоксы в WordPress, удаление стандартных и добавление собственных

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

remove_meta_box() — удаление метабоксов

remove_meta_box( $id, $page, $context );
  • $id (строка)
    идентификатор метабокса, его можно найти в исходном коде странице, чуть ниже я перечислю айдишники всех стандартных метабоксов.
  • $page (строка)
    тип постов, на странице создания/редактирования которых нужно удалить метабокс, например post, page.
  • $context (строка)
    расположение метабокса, например normal, advanced или side

Простая вставка этой функции куда-либо не прокатит, поэтому привожу пример:

/*
 * удаляем со страницы редактирования постов метабокс с рубриками и цитатой
 */
function remove_category_div() {
    remove_meta_box( 'categorydiv' , 'post' , 'side' ); // рубрики
    remove_meta_box( 'postexcerpt' , 'post' , 'normal' ); // цитата
}
add_action( 'admin_menu' , 'remove_category_div' );

Код вставлять в functions.php текущей темы.

Описание стандартных метабоксов в WordPress

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

  • commentstatusdiv — настройки обсуждения,
    метабокс commentstatusdiv
  • commentsdiv — отображает комментарии к текущему посту,
    метабокс commentsdiv в WordPress
  • slugdiv — ярлык записи,
    slugdiv метабокс
  • revisionsdiv — редакции,
    метабокс с редакциями, revisionsdiv
  • authordiv — автор записи,
    authordiv метабокс
  • postcustom — добавление/редактирование произвольных полей,
    postcustom, метабокс произвольных полей
  • postexcerpt — цитата,
    postexcerpt, метабокс цитаты
  • trackbacksdiv — обратные ссылки,
    метабокс trackbacksdiv в WordPress
  • categorydivсписок рубрик,
    categorydiv, метабокс с рубриками
  • tagsdiv-post_tag — метки,
    tagsdiv-post_tag
  • postimagediv — миниатюра записи,
    postimagediv, миниатюра записи
  • pageparentdiv — метабокс с выбором родительской страницы и шаблона страниц,
    pageparentdiv, атрибуты страницы
  • submitdiv — блок с кнопкой «опубликовать».
    submitdiv, метабокс в WordPress

Способы добавления метабоксов

register_post_type()

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

В примере перечислено лишь минимум необходимых параметров, но он все равно рабочий.

function true_register_post_type_example(){
    $args = array(
        'hierarchical' => true,
        'show_ui' => true, 
        /*
         * присвоив таксономию для поста, мы автоматически подключаем метабокс этой таксономии
         */
        'taxonomies' => array('category'),
        /*
         * а теперь прописываем уже сами названия метабоксов,
         * названия для register_post_type() и для remove_meta_box() будут отличаться!!
         */
        'supports' => array( 'title', 'editor' )
        /*
         * Возможные варианты содержимого массива "supports":
         *
         * title - заголовок,
         * editor - редактор,
         * author - автор записи,
         * thumbnail - миниатюра записи,
         * excerpt - поле для цитаты,
         * trackbacks - обратные ссылки,
         * custom-fields - произвольные поля,
         * comments - комментарии,
         * revisions - редакции,
         * page-attributes - атрибуты поста, только при 'hierarchical' => true
         *
         */
    );
    register_post_type('truepost', $args);
}
 
add_action( 'init', 'true_register_post_type_example' );

register_taxonomy_for_object_type()

Функция приписывает таксономию к уже созданному типу записей, а значит, добавляется и метабокс:

register_taxonomy_for_object_type($taxonomy, $object_type);
  • $taxonomy (строка) (обязательное)
    название таксономии, например post_tag,
  • $object_type (строка) (обязательное)
    тут укажите тип поста, для которого нужно присвоить таксономию, например post, page, game;

Эту функцию тоже просто так не заюзать, поэтому пример:

function true_additional_taxonomies(){
    register_taxonomy_for_object_type('post_tag', 'truepost');
}
 
add_action( 'init', 'true_additional_taxonomies' );

add_post_type_support()

Позволяет добавить какой-нибудь из стандартных боксов.

add_post_type_support( $post_type, $supports )
  • $post_type (строка) (обязательное)
    тип поста (максимум 20 символов кстати),
  • $supports (строка|массив)
    названия стандартных метабоксов, которые перечислены двумя примерами выше;
function add_some_std_metaboxes() {
    add_post_type_support('game', 'excerpt'); // цитата
    add_post_type_support('truepost', array('excerpt', 'thumbnail')); // цитата и миниатюра
}
 
add_action('init', 'add_some_std_metaboxes');

add_meta_box()

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

add_meta_box($id, $title, $callback, $post_type, $context, $priority, $args);
  • $id (строка) (обязательное)
    HTML-атрибут id для блока div будущего метабокса,
  • $title (строка) (обязательное)
    заголовок,
  • $callback (функция) (обязательное)
    функция которая будет заполнять метабокс, нужно указать название функции в виде строки,
  • $post_type (строка) (обязательное)
    тип записей,
  • $context (строка)
    в какой части страницы вставить метабокс (normal, side, advanced), по умолчанию — advanced,
  • $priority (строка)
    приоритет, чем он выше, тем ближе к верхней части страницы будет располагаться метабокс, (high, core, default или low), по умолчанию — default,
  • $args (массив)
    аргументы для callback-функции.

В отличие от предыдущих способов, здесь добавление будет проходить в несколько этапов, посмотрим на примере:

<?php
/*
 * Этап 1. Добавление
 */
function true_meta_boxes() {
    add_meta_box('truediv', 'Настройки', 'true_print_box', 'post', 'normal', 'high');
}
 
add_action( 'admin_menu', 'true_meta_boxes' );
/*
 * также можно использовать и другие хуки:
 * add_action( 'add_meta_boxes', 'tr_meta_boxes' );
 * если версия WordPress ниже 3.0, то
 * add_action( 'admin_init', 'tr_meta_boxes', 1 );
 */
 
/*
 * Этап 2. Заполнение
 */
function true_print_box($post) {
    wp_nonce_field( basename( __FILE__ ), 'seo_metabox_nonce' );
    /*
     * добавляем текстовое поле
     */
    $html .= '<label>Заголовок <input type="text" name="seotitle" value="' . get_post_meta($post->ID, 'seo_title',true) . '" /></label> ';
    /*
     * добавляем чекбокс
     */
    $html .= '<label><input type="checkbox" name="noindex"';
    $html .= (get_post_meta($post->ID, 'seo_noindex',true) == 'on') ? ' checked="checked"' : '';
    $html .= ' /> Скрыть запись от поисковиков?</label>';
 
    echo $html;
}
 
/*
 * Этап 3. Сохранение
 */
function true_save_box_data ( $post_id ) {
    // проверяем, пришёл ли запрос со страницы с метабоксом
    if ( !isset( $_POST['seo_metabox_nonce'] )
    || !wp_verify_nonce( $_POST['seo_metabox_nonce'], basename( __FILE__ ) ) )
        return $post_id;
    // проверяем, является ли запрос автосохранением
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
        return $post_id;
    // проверяем, права пользователя, может ли он редактировать записи
    if ( !current_user_can( 'edit_post', $post_id ) )
        return $post_id;
    // теперь также проверим тип записи   
    $post = get_post($post_id);
    if ($post->post_type == 'post') { // укажите собственный
        update_post_meta($post_id, 'seo_title', esc_attr($_POST['seotitle']));
        update_post_meta($post_id, 'seo_noindex', $_POST['noindex']);
    }
    return $post_id;
}
 
add_action('save_post', 'true_save_box_data');

В итоге на странице редактирования поста получаем вот такой метабоксик:

собственный метабокс с настройками в вордпресс

Код можно вставить прямо в таком виде в functions.php — и всё будет работать, если конечно у вас нет функций, названия которых совпадают с моими.

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

На самом деле это просто потрясающая штука!

  • достаточно один раз описать класс и затем сколько угодно использовать его для добавления метабоксов на сайте,
  • не придется каждый раз париться по поводу HTML полей ввода, как в случае с функцией add_meta_box(),
  • все, что потребуется для создания нового метабокса — добавить несколько параметров в массив;

А теперь у меня для вас подарок! Уже готовый класс со всеми необходимыми типами полей.

Расскажу, как его использовать в двух шагах. Первый шаг — скопируйте к себе следующий блок с кодом. Если не знаете куда его засунуть — суйте в functions.php, не ошибетесь.

<?php
class trueMetaBox {
    function __construct($options) {
        $this->options = $options;
        $this->prefix = $this->options['id'] .'_';
        add_action( 'add_meta_boxes', array( &$this, 'create' ) );
        add_action( 'save_post', array( &$this, 'save' ), 1, 2 );
    }
    function create() {
        foreach ($this->options['post'] as $post_type) {
            if (current_user_can( $this->options['cap'])) {
                add_meta_box($this->options['id'], $this->options['name'], array(&$this, 'fill'), $post_type, $this->options['pos'], $this->options['pri']);
            }
        }
    }
    function fill(){
        global $post; $p_i_d = $post->ID;
        wp_nonce_field( $this->options['id'], $this->options['id'].'_wpnonce', false, true );
        ?>
        <table class="form-table"><tbody><?php
        foreach ( $this->options['args'] as $param ) {
            if (current_user_can( $param['cap'])) {
            ?><tr><?php
                if(!$value = get_post_meta($post->ID, $this->prefix .$param['id'] , true)) $value = $param['std'];
                switch ( $param['type'] ) {
                    case 'text':{ ?>
                        <th scope="row"><label for="<?php echo $this->prefix .$param['id'] ?>"><?php echo $param['title'] ?></label></th>
                        <td>
                            <input name="<?php echo $this->prefix .$param['id'] ?>" type="<?php echo $param['type'] ?>" id="<?php echo $this->prefix .$param['id'] ?>" value="<?php echo $value ?>" placeholder="<?php echo $param['placeholder'] ?>" class="regular-text" /><br />
                            <span class="description"><?php echo $param['desc'] ?></span>
                        </td>
                        <?php
                        break;                          
                    }
                    case 'textarea':{ ?>
                        <th scope="row"><label for="<?php echo $this->prefix .$param['id'] ?>"><?php echo $param['title'] ?></label></th>
                        <td>
                            <textarea name="<?php echo $this->prefix .$param['id'] ?>" type="<?php echo $param['type'] ?>" id="<?php echo $this->prefix .$param['id'] ?>" value="<?php echo $value ?>" placeholder="<?php echo $param['placeholder'] ?>" class="large-text" /><?php echo $value ?></textarea><br />
                            <span class="description"><?php echo $param['desc'] ?></span>
                        </td>
                        <?php
                        break;                          
                    }
                    case 'checkbox':{ ?>
                        <th scope="row"><label for="<?php echo $this->prefix .$param['id'] ?>"><?php echo $param['title'] ?></label></th>
                        <td>
                            <label for="<?php echo $this->prefix .$param['id'] ?>"><input name="<?php echo $this->prefix .$param['id'] ?>" type="<?php echo $param['type'] ?>" id="<?php echo $this->prefix .$param['id'] ?>"<?php echo ($value=='on') ? ' checked="checked"' : '' ?> />
                            <?php echo $param['desc'] ?></label>
                        </td>
                        <?php
                        break;                          
                    }
                    case 'select':{ ?>
                        <th scope="row"><label for="<?php echo $this->prefix .$param['id'] ?>"><?php echo $param['title'] ?></label></th>
                        <td>
                            <label for="<?php echo $this->prefix .$param['id'] ?>">
                            <select name="<?php echo $this->prefix .$param['id'] ?>" id="<?php echo $this->prefix .$param['id'] ?>"><option>...</option><?php
                                foreach($param['args'] as $val=>$name){
                                    ?><option value="<?php echo $val ?>"<?php echo ( $value == $val ) ? ' selected="selected"' : '' ?>><?php echo $name ?></option><?php
                                }
                            ?></select></label><br />
                            <span class="description"><?php echo $param['desc'] ?></span>
                        </td>
                        <?php
                        break;                          
                    }
                } 
            ?></tr><?php
            }
        }
        ?></tbody></table><?php
    }
    function save($post_id, $post){
        if ( !wp_verify_nonce( $_POST[ $this->options['id'].'_wpnonce' ], $this->options['id'] ) ) return;
        if ( !current_user_can( 'edit_post', $post_id ) ) return;
        if ( !in_array($post->post_type, $this->options['post'])) return;
        foreach ( $this->options['args'] as $param ) {
            if ( current_user_can( $param['cap'] ) ) {
                if ( isset( $_POST[ $this->prefix . $param['id'] ] ) && trim( $_POST[ $this->prefix . $param['id'] ] ) ) {
                    update_post_meta( $post_id, $this->prefix . $param['id'], trim($_POST[ $this->prefix . $param['id'] ]) );
                } else {
                    delete_post_meta( $post_id, $this->prefix . $param['id'] );
                }
            }
        }
    }
}

Вставили и забыли, если не уверены, лучше в этом коде ничего не менять. Если не пашет — пишите в комментариях или мне на почте, лучше конечно в комментариях. На своем тестовом сайте я протестировал — всё ок.

Теперь шаг второй — создаем объекты и передаем им все параметры метабоксов.

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

$options = array(
    array( // первый метабокс
        'id'    =>   'meta1', // ID метабокса, а также префикс названия произвольного поля
        'name'  =>   'Доп. настройки 1', // заголовок метабокса
        'post'  =>   array('post'), // типы постов для которых нужно отобразить метабокс
        'pos'   =>   'normal', // расположение, параметр $context функции add_meta_box()
        'pri'   =>   'high', // приоритет, параметр $priority функции add_meta_box()
        'cap'   =>   'edit_posts', // какие права должны быть у пользователя
        'args'  =>   array(
            array(
                'id'            =>   'field_1', // атрибуты name и id без префикса, например с префиксом будет meta1_field_1
                'title'         =>   'Текст', // лейбл поля
                'type'          =>   'text', // тип, в данном случае обычное текстовое поле
                'placeholder'       =>   'плейсхолдер, например введите email', // атрибут placeholder
                'desc'          =>   'пример использования текстового поля ввода в метабоксе', // что-то типа пояснения, подписи к полю
                'cap'           =>   'edit_posts'
            ),
            array(
                'id'            =>   'terms',
                'title'         =>   'Чекбокс',
                'type'          =>   'checkbox', // чекбокс
                'desc'          =>   'пример чекбокса',
                'cap'           =>   'edit_posts'
            ),
            array(
                'id'            =>   'textfield',
                'title'         =>   'Текстовое поле',
                'type'          =>   'textarea', // большое текстовое поле
                'placeholder'       =>   'сюда тоже можно забацать плейсхолдер',
                'desc'          =>   'пример использования большого текстового поля ввода в метабоксе',
                'cap'           =>   'edit_posts'
            ),
            array(
                'id'            =>   'select1',
                'title'         =>   'Выпадающий список',
                'type'          =>   'select', // выпадающий список
                'desc'          =>   'тут тоже можно написать пояснение к полю, значения же задаются через ассоциативный массив',
                'cap'           =>   'edit_posts',
                'args'          =>   array('value_1' => 'Значение 1', '2' => 'Значение 2', 'Значение_3' => 'Значение 3' ) // элементы списка задаются через массив args, по типу value=>лейбл
            )
        )
    ),
    array( // второй метабокс
        'id'    =>   'meta2',
        'name'  =>   'Доп. настройки 2',
        'post'  =>   array('post', 'page'), // не только для постов, но и для страниц
        'pos'   =>   'normal',
        'pri'   =>   'high',
        'cap'   =>   'edit_posts',
        'args'  =>   array(
            array(
                'id'            =>   'featured',
                'title'         =>   'На главную',
                'desc'          =>   'Отображать пост на главной странице',
                'type'          =>   'checkbox',
                'cap'           =>   'edit_posts'
            )
        )
    )
);
 
foreach ($options as $option) {
    $truemetabox = new trueMetaBox($option);
}

Вот скриншот получившихся метабоксов из админки, со страницы редактирования записи:

метабоксы в вордпресс

Обращение к метаданным поста/страницы

Понятное дело, что потом все эти настройки нужно как-то задействовать на сайте. Для этого отлично подойдет функция:

get_post_meta($post_id, $key, $single);
  • $post_id (целое) (обязательное)
    ID поста или страницы,
  • $key (строка) (обязательное)
    значение произвольного поля,
  • $single (логическое)
    если true — возвращает строку, false — массив, по умолчанию — false;

Пример использования — выведем значение произвольного поля meta1_field_1, то есть текстового поля из предыдущего примера:

echo get_post_meta($post->ID, 'meta1_field_1', true);

По мере совершенствования класса содержимое этого поста будет обновляться.

Источник: misha.blog

Миша Рудрастых

Путешествует по миру и рассказывает всем о WordPress лично, у себя в блогах и на курсах в Санкт-Петербурге. Умеет просто объяснять сложные вещи, делает это красиво. Организовывает неплохие WordCamp's, но совсем не умеет слушать чужие доклады.

Добавить комментарий

%d такие блоггеры, как: