Сейчас у многих слово «метабокс» ассоциируется с каким-нибудь плагином, например «Advanced Custom Fields» или Carbon Fields. Но метабоксы – это стандартный функционал WordPress из коробки.
А плагины наплодились лишь потому, что при помощи них можно довольно легко сократить количество кода, необходимого для написания метабоксов, причём очень значительно – раз в 10. Ну и некоторые, наиболее ловкие разработчики сделали «ни рыбу ни мясо», подпилив для этого интерфейс в админке. Что вообще смешно – для создания метабокса вы можете воспользоваться интерфейсом в админке, но зато вы никак не сможете воспользоваться этими данными на самом сайте, потому что там то нужно воспользоваться кодом для вывода этих полей (смеюсь уже который год, не могу остановиться).
Удаление метабоксов
Любой из метабоксов можно удалить функцией remove_meta_box(). Единственное условие – сам метабокс должен создаваться до удаления, а не наоборот. В этом случае оптимально вешать её на хук add_meta_boxes
с высоким приоритетом.
Например в сниппете ниже мы удлаяем метабоксы «Рубрики» и «Отрывок».
add_action( 'add_meta_boxes' , 'true_remove_meta_boxes' ); function true_remove_meta_boxes() { // метабокс рубрик remove_meta_box( 'categorydiv', 'post', 'side' ); // метабокс отрывка записи remove_meta_box( 'postexcerpt', 'post', 'normal' ); }
Стандартные метабоксы WordPress
Также для вашего удобства решил перечислить айдишники и описания стандартных метабоксов в WordPress. Конечно, Gutenberg уже пришёл и метабоксы эти есть не всегда, у вас либо тип записи не должен поддерживать Gutenberg, либо включен плагин Classic Editor. И тем не менее.
commentstatusdiv
– метабокс с настройками обсуждения.
commentsdiv
– отображает комментарии к текущему посту.
slugdiv
– ярлык записи.
revisiondiv
– редакции записи.
authordiv
– метабокс с автором поста.
postcustom
– метабокс управления произвольными полями.
postexcerpt
– метабокс с отрывком записи.
trackbackdiv
– обратные ссылки.
categorydiv
– Рубрики записи.
tagsdiv-post_tag
– Метки записи.
postimagediv
– метабокс с изображением записи.
postparentdiv
– метабокс с атрибутами поста или страницы. Отображается либо если для данного типа записи существуют произвольные шаблоны, либо если тип записи с иерархией.
formatdiv
– метабокс с форматами записи.
submitdiv
– блок с кнопкой «опубликовать».
Создание собственного метабокса
Прежде, чем мы приступим к созданию своего прекрасного SEO-метабокса, хочу также обратить ваше внимание, что мы можем управлять тем, какие стандартные метабоксы отображаются для определённых типов постов, например мы можем задать это при регистрации функцией register_post_type(), или же добавить функциями register_taxonomy_for_object_type() или add_post_type_support().
Ну погнали.
Вот так будем выглядеть наш метабокс и состоять из пары полей, необходимых для SEO:
1. Регистрация метабокса функцией add_meta_box()
Начнём с функции add_meta_box(), про которую вы кстати можете почитать отдельно у меня на блоге. Единственный момент – вы не можете использовать эту функцию внутри functions.php
напрямую, вам понадобится либо повесить её на хук admin_menu
, либо на add_meta_boxes
.
add_action( 'add_meta_boxes', 'true_add_metabox' ); function true_add_metabox() { add_meta_box( 'seo_metabox', // ID нашего метабокса 'SEO настройки поста', // заголовок 'seo_metabox_callback', // функция, которая будет выводить поля в мета боксе 'page', // типы постов, для которых его подключим 'normal', // расположение (normal, side, advanced) 'default' // приоритет (default, low, high, core) ); } function seo_metabox_callback( $post ) { echo 'приветик'; }
После вставки этого кода, надеюсь вы знаете куда, у нас получается следующее:
2. Добавляем поля в метабокс
Теперь давайте попробуем вывести в метабоксе нечто большее, чем просто «приветик». Например я бы добавил обычное текстовое поле с SEO-заголовком поста и чекбокс для скрытия его от поисковиков.
function seo_metabox_callback( $post ) { // сначала получаем значения этих полей // заголовок $seo_title = get_post_meta( $post->ID, 'seo_title', true ); // скрытие от поисковиков $seo_robots = get_post_meta( $post->ID, 'seo_robots', true ); // одноразовые числа, кстати тут нет супер-большой необходимости их использовать wp_nonce_field( 'seopostsettingsupdate-' . $post->ID, '_truenonce' ); echo '<table class="form-table"> <tbody> <tr> <th><label for="seo_title">SEO-заголовок</label></th> <td><input type="text" id="seo_title" name="seo_title" value="' . esc_attr( $seo_title ) . '" class="regular-text"></td> </tr> <tr> <th>Скрыть из поисковиков</th> <td> <label><input type="checkbox" name="seo_robots" ' . checked( 'yes', $seo_robots, false ) . ' /> Да</label> </td> </tr> </tbody> </table>'; }
Во-первых, вот как станет выглядеть наш метабокс, после того, как вы измените содержимое callback-функции.
Во-вторых, есть несколько комментариев относительно кода:
3. Сохранение значений полей метабокса
Тут мы будем использовать хук save_post
и, как вы можете заметить, тут уже значительное количество кода и как раз поэтому все и используют плагины для создания метабоксов.
add_action( 'save_post', 'true_save_meta', 10, 2 ); function true_save_meta( $post_id, $post ) { // проверка одноразовых полей if ( ! isset( $_POST[ '_truenonce' ] ) || ! wp_verify_nonce( $_POST[ '_truenonce' ], 'seopostsettingsupdate-' . $post->ID ) ) { return $post_id; } // проверяем, может ли текущий юзер редактировать пост $post_type = get_post_type_object( $post->post_type ); if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) { return $post_id; } // ничего не делаем для автосохранений if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) { return $post_id; } // проверяем тип записи if( 'page' !== $post->post_type ) { return $post_id; } if( isset( $_POST[ 'seo_title' ] ) ) { update_post_meta( $post_id, 'seo_title', sanitize_text_field( $_POST[ 'seo_title' ] ) ); } else { delete_post_meta( $post_id, 'seo_title' ); } if( isset( $_POST[ 'seo_robots' ] ) && 'on' == $_POST[ 'seo_robots' ] ) { update_post_meta( $post_id, 'seo_robots', 'yes' ); } else { delete_post_meta( $post_id, 'seo_robots' ); } return $post_id; }
4. Вывод полей на сайте
Для этого мы будем всего лишь использовать функцию get_post_meta(). Получается, нам нужно вывести SEO-тайтл, если он существует и мета-тег роботс.
С SEO-тайтлом лучше всего воспользоваться хуком pre_get_document_title. Также я добавил условие is_page(), ведь наш метабокс и так выводится только для страниц.
add_filter( 'pre_get_document_title', 'true_seo_title', 25 ); function true_seo_title(){ if( is_page() && ( $title = get_post_meta( get_the_ID(), 'seo_title', true ) ) ) { return $title; } return ''; }
Что же делаем с метатегов robots? Думаю, что сгодится хук wp_head, но тут лучше прочекать, как устроена ваша тема.
add_action( 'wp_head', 'true_seo_robots', 25 ); function true_seo_robots() { if( ! is_page() ) { return; } if( 'yes' === get_post_meta( get_the_ID(), 'seo_robots', true ) ) { echo '<meta name="robots" content="noindex,nofollow" />'; } }
Делаем то же самое при помощи Carbon Fields
Я уже говорил, что каждый раз писать весь этот код в некоторых ситуациях может быть нецелесообразно и неэффективно по времени. Поэтому хочу обратить ваше внимание на код, который создаёт точно такой же метабокс при помощи бесплатного плагина Carbon Fields, вот кстати руководство по нему.
use Carbon_FieldsContainer; use Carbon_FieldsField; add_action( 'carbon_fields_register_fields', 'truemisha_carbon_seo' ); function truemisha_carbon_seo() { Container::make( 'post_meta', 'SEO настройки поста' ) ->where( 'post_type', '=', 'page' ) ->add_fields( array( Field::make( 'text', 'seo_title', 'SEO-заголовок' ), Field::make( 'checkbox', 'seo_robots', 'Скрыть из поисковиков' )->set_option_value( 'yes' ) ) ); }
Это весь код. Чтоооо?