Когда вы разрабатываете тему или плагин, иногда возникает необходимость добавить некий функционал, который должен существовать помимо стандартного, реализованного в WordPress "из коробки", а именно записей и страниц. С одной стороны, такой функционал можно добавить с помощью плагинов, с другой - не всегда тот вариант отображения информации, который предлагается разработчиками плагинов, устраивает именно вас.В этом случае на помощь приходит возможность добавить в WordPress свои, пользовательские, или кастомные типы записей, которые будут решать те задачи, которые важны прежде всего для вас.
В этой статье мы будем создавать пользовательские типы записей, связанные с отзывами. Это достаточно популярный элемент любого сайта, продающего товары или услуги. Например, плагин Elementor имеет виджет, позволяющий добавлять отзывы на любую страницу.
Итак, при создании отзывов здесь мы будем двигаться следующим путем:
- Шаг 1. Регистрируем тип записи с названием testimonial
- Шаг 2. Регистрируем мета-бокс
- Шаг 3. Добавляем отзывы
- Шаг 4. Создаем файл для отображения одного отзыва
- Шаг 5. Добавляем файл таксономии
- Шаг 6. Файлы переводов
Шаг 1. Регистрируем тип записи с названием testimonial.
Вы можете регистрировать тип записи в файле functions.php. Однако этот файл, как правило, содержит массу разных функций, которые далеко не всегда связаны друг с другом. Поэтому имеет смысл вынести вседействия, связанные с вашим типом записи в отдельный файл и даже в отдельную директорию. Довольно часто для различных добавочных файлов в теме используют папку inc (от англ. include - включать). Сам файл можно назвать post-types.php.
Обязательно нужно указать в functions.php, что вы загружаете этот файл для работы с ним в теме:
1 2 3 4 | define('THEME_DIR', get_template_directory()); define('THEME_URI', get_template_directory_uri()); require THEME_DIR . '/inc/post-types.php'; |
В том случве, если вы создаете пользовательский тип записи для дочерней темы WordPress, вам нужно изменить пути к папкам, т.к. функции get_template_directory()
и get_template_directory_uri()
ведут к каталогу основной (родительской) темы, в которой указанного файла нет.
1 2 3 4 | define('THEME_DIR', get_stylesheet_directory()); define('THEME_URI', get_stylesheet_directory_uri()); require THEME_DIR . '/inc/post-types.php'; |
Теперь вы можете быть уверены, что ваш новый тип записи будет отображен в админке.
В том случае, когда у вас сайт на одном языке, вы можете сразу же указывать название типов записей и таксономий на языке сайта. Если сайт мультиязычный, лучше использовать функцию __('name', 'theme-name')
название темы для последующего создания файлов перевода.
1 2 3 4 5 6 7 8 9 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 | <?php function theme_slug_post_type_testimonials() { $labels = array( 'name' => __( 'Testimonial', 'theme-name' ), 'singular_name' => __( 'Testimonial', 'theme-name' ), 'add_new' => __( 'Add New', 'theme-name' ), 'add_new_item' => __( 'Add New Testimonial', 'theme-name' ), 'edit_item' => __( 'Edit Testimonial' ), 'new_item' => __( 'New Testimonial', 'theme-name' ), 'all_items' => __( 'All Testimonials', 'theme-name' ), 'view_item' => __( 'View Testimonial', 'theme-name' ), 'search_items' => __( 'Search Testimonial', 'theme-name' ), 'not_found' => __( 'No Testimonials found', 'theme-name' ), 'not_found_in_trash' => __( 'No Testimonials found in the Trash', 'theme-name' ), 'parent_item_colon' => '', 'menu_name' => 'Testimonials' ); $args = array( 'labels' => $labels, 'description' => 'Displays testimonials', 'public' => true, 'exclude_from_search' => true, 'menu_position' => 5, 'menu_icon' => 'dashicons-testimonial', 'supports' => array( 'title', 'thumbnail', 'editor' ), 'show_in_rest' => true, //support Gutenberg Editor 'taxonomies' => array( 'testimonial_category' ), 'has_archive' => false, ); register_post_type( 'testimonial', $args ); } add_action('init', 'theme_slug_post_type_testimonials'); |
Чтобы ваш новый тип записи появился в админке, нужно обязательно добавить функцию регистрации с помощью хука add_action('init', 'theme_slug_post_type_testimonials')
.
А теперь внимание - есть еще один подвох, выделенный в коде выше. Он говорит о том, что данный тип записи (testimonials) поддерживает таксономию 'testimonial_category'
. По сути дела это категории для ваших отзывов, которые могут выводится в разных местах темы. Таксономии тоже нужно регистрировать.
register_post_type()
.Код будет теперь таким:
1 2 3 4 5 6 7 8 9 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 | <?php function theme_slug_post_type_testimonials() { register_taxonomy( 'testimonial_category', 'testimonial', array( 'labels' => array( 'name' => __( 'Testimonial Categories', 'theme-name' ), 'singular_name' => __( 'Testimonial Category', 'theme-name' ), 'search_items' => __( 'Search Testimonial Categories', 'theme-name' ), 'all_items' => __( 'All Testimonial Categories', 'theme-name' ), 'edit_item' => __( 'Edit Testimonial Categories', 'theme-name' ), 'update_item' => __( 'Update Testimonial Category', 'theme-name' ), 'add_new_item' => __( 'Add New Testimonial Category', 'theme-name' ), 'new_item_name' => __( 'New Testimonial Category Name', 'theme-name' ), 'menu_name' => __( 'Testimonial Category', 'theme-name' ), ), 'hierarchical' => true, 'sort' => true, 'args' => array( 'orderby' => 'term_order' ), 'show_admin_column' => true ) ); $labels = array( 'name' => __( 'Testimonial', 'theme-name' ), 'singular_name' => __( 'Testimonial', 'theme-name' ), 'add_new' => __( 'Add New', 'theme-name' ), 'add_new_item' => __( 'Add New Testimonial', 'theme-name' ), 'edit_item' => __( 'Edit Testimonial' ), 'new_item' => __( 'New Testimonial', 'theme-name' ), 'all_items' => __( 'All Testimonials', 'theme-name' ), 'view_item' => __( 'View Testimonial', 'theme-name' ), 'search_items' => __( 'Search Testimonial', 'theme-name' ), 'not_found' => __( 'No Testimonials found', 'theme-name' ), 'not_found_in_trash' => __( 'No Testimonials found in the Trash', 'theme-name' ), 'parent_item_colon' => '', 'menu_name' => 'Testimonials' ); $args = array( 'labels' => $labels, 'description' => 'Displays testimonials', 'public' => true, 'exclude_from_search' => true, 'menu_position' => 5, 'menu_icon' => 'dashicons-testimonial', 'supports' => array( 'title', 'thumbnail', 'editor' ), //'show_in_rest' => true, //поддержка редактора Gutenberg (если нужна) 'taxonomies' => array( 'testimonial_category' ), 'has_archive' => false, ); register_post_type( 'testimonial', $args ); } add_action('init', 'theme_slug_post_type_testimonials'); |
Теперь мы можем заглянуть в админку и увидеть наш тип записи:
На данный момент у вас нет ни одного отзыва, но сам пункт в админке есть + возможность добавлять категории для отзывов. Давайте этим займемся на 3-м шаге, а сейчас ...
Шаг 2. Регистрируем мета-бокс
Как правило, тех полей, которые мы можем добавить по умолчанию, а это заголовок записи, изображение и текстовая область для контента, бывает недостаточно. В этой статье мы будем добавлять отзывы для сайта курсов по психологии. Поэтому в заголовке мы будем указывать автора отзыва, в области контента поместим сам отзыв, изображение будем использовать в качестве изображения автора отзыва (возьмем их с сайта unsplash.com). Курс - это таксономия (категория) отзывов. Но нам нужно еще указать преподавателя курса. Для этого нам понадобится дополнительное поле (meta_box в терминологии WordPress).
Для этого в массив $args
добавим строку 'register_meta_box_cb' => 'register_meta_box'
, а затем пропишем функции, которые регистрируют это мета-поле, а также сохраняют днные из этого поля и обновляют их.
1 2 3 4 5 6 7 8 9 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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | <?php function theme_slug_post_type_testimonials() { register_taxonomy( 'testimonial_category', 'testimonial', array( 'labels' => array( 'name' => __( 'Testimonial Categories', 'theme-name' ), 'singular_name' => __( 'Testimonial Category', 'theme-name' ), 'search_items' => __( 'Search Testimonial Categories', 'theme-name' ), 'all_items' => __( 'All Testimonial Categories', 'theme-name' ), 'edit_item' => __( 'Edit Testimonial Categories', 'theme-name' ), 'update_item' => __( 'Update Testimonial Category', 'theme-name' ), 'add_new_item' => __( 'Add New Testimonial Category', 'theme-name' ), 'new_item_name' => __( 'New Testimonial Category Name', 'theme-name' ), 'menu_name' => __( 'Testimonial Category', 'theme-name' ), ), 'hierarchical' => true, 'sort' => true, 'args' => array( 'orderby' => 'term_order' ), 'show_admin_column' => true ) ); $labels = array( 'name' => __( 'Testimonial', 'theme-name' ), 'singular_name' => __( 'Testimonial', 'theme-name' ), 'add_new' => __( 'Add New', 'theme-name' ), 'add_new_item' => __( 'Add New Testimonial', 'theme-name' ), 'edit_item' => __( 'Edit Testimonial' ), 'new_item' => __( 'New Testimonial', 'theme-name' ), 'all_items' => __( 'All Testimonials', 'theme-name' ), 'view_item' => __( 'View Testimonial', 'theme-name' ), 'search_items' => __( 'Search Testimonial', 'theme-name' ), 'not_found' => __( 'No Testimonials found', 'theme-name' ), 'not_found_in_trash' => __( 'No Testimonials found in the Trash', 'theme-name' ), 'parent_item_colon' => '', 'menu_name' => __('Testimonials', 'theme-name' ), ); $args = array( 'labels' => $labels, 'description' => 'Displays testimonials', 'public' => true, 'exclude_from_search' => true, 'menu_position' => 5, 'menu_icon' => 'dashicons-testimonial', 'supports' => array( 'title', 'thumbnail', 'editor' ), //'show_in_rest' => true, //поддержка редактора Gutenberg (если нужна) 'taxonomies' => array( 'testimonial_category' ), 'has_archive' => false, 'register_meta_box_cb' => 'register_meta_box', ); register_post_type( 'testimonial', $args ); } add_action('init', 'theme_slug_post_type_testimonials'); function register_meta_box() { add_meta_box( 'teacher_name', __('Teacher Name', 'theme_slug'), 'testimonial_meta_html', 'testimonial', 'side' ); } function testimonial_meta_html() { global $post; $nonce_key = 'testimonial_fields_nonce'; $link_meta_key = 'teacher_name'; wp_nonce_field($nonce_key, $nonce_key); $link = get_post_meta( $post->ID, $link_meta_key, true ); echo '<input type="text" id="teacher_name" name="teacher_name" class="widefat" value="'.$link.'">'; } function save_testimonial_meta($post_id, $post) { $nonce_key = 'testimonial_fields_nonce'; $link_meta_key = 'teacher_name'; $link_field_name = 'teacher_name'; $custom_post_type = 'testimonial'; // проверяем nonce if (!isset($_POST[$nonce_key]) || !wp_verify_nonce($_POST[$nonce_key], $nonce_key)) return 'nonce not verified'; // проверяем автосохранение if (wp_is_post_autosave($post_id )) return 'autosave'; //проверяем ревизии записи if (wp_is_post_revision($post_id)) return 'revision'; // проверяем разрешения if ( ! current_user_can( 'edit_post', $post_id ) ) { return 'cannot edit post'; } $link_field_name = $_POST[$link_field_name]; update_post_meta($post_id, $link_meta_key, $link_field_name ); } add_action( 'save_post', 'save_testimonial_meta', 10,2); |
Теперь можем добавить отзывы в админке сайта.
Шаг 3. Добавляем отзывы
В результате у нас появится возможность создавать новые записи типа testimonial, о чем свидетельствует постоянная ссылка.
Шаг 4. Создаем файл для отображения одного отзыва
Настройки → Постоянные ссылки
. Нужно это для того, чтобы правила ЧПУ были пересозданы и туда были добавлены правила нового типа записи. Если вы этого не сделаете, потом не сможете просмотреть страницу с отзывом или с таксономией.На данный момент мы можем посмотреть этот отзыв в том виде, в котором это позволяет тема, выбранная для сайта. За внешний вид одиночной записи отвечает файл single.php
, в том числе, если эта запись кастомная,
Если же нам нужен какой-то особый вид, то нужно создать специальный файл. Его название должно быть вида single-{post_type}.php
. То есть для типа записи (post_type
) testimonial должен быть файл с названием single-testimonial.php
с нужным вам содержимым.
Ниже представлен довольно простой вариант разметки. Для вашей темы он может отличаться от предложенного ниже.
1 2 3 4 5 6 7 8 9 10 11 12 | <?php /* Single for post type testimonials */ get_header(); ?> <div class="container" role="main"> <article id="post-<?php the_ID(); ?>" <?php post_class('article'); ?>> <?php get_template_part( 'inc/testimonial' ); ?> </article> </main> <?php get_sidebar('right'); get_footer(); |
В коде на строке 7 использована функция get_template_part(). Она подразумевает, что в папке 'inc' нашей темы находится файл testimonial.php. Код в нем будет примерно таким:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <div class="testimonial-block"> <?php $terms = get_the_terms ( get_the_ID(), 'testimonial_category' ); // получаем данные о категории, если она указана if($terms) { $tax_category_name = $terms[0]->name; $tax_category_link = site_url('/').'testimonial_category/'.$terms[0]->slug; // формируем заголовок курса со ссылкой echo '<h3>Курс <a href="'. $tax_category_link. '">'. $tax_category_name.'</a></h3>'; } ?> <div class="testimonial-text"> <?php the_content(); ?> </div><!-- /testimonial-text --> <div class="flex-row"> <div class="testimonial-teacher"> <p>Преподаватель:</p> <?php echo get_post_meta(get_the_ID(), 'teacher_name', true); ?></div> // получаем данные мета-бокса <div class="testimonial-title flex-row"> <?php if(has_post_thumbnail()){ the_post_thumbnail( 'thumbnail', ['class'=>'img-circle'] ); //выводим изображение, если оно есть } ?> <div class="author"> <p>Автор:</p> <?php the_title(); ?> </div> </div> </div> </div> |
С простыми стилями для блока отзыва наш файл single-testimonial.php выглядит так:
Мы можем увидеть отображение отзыва, перейдя по ссылке в админке.
Шаг 5. Добавляем файл таксономии
Для того чтобы ссылка на курс в предыдущем нашем файле single-testimonial.php работала, нам понадобится файл, который выводит все данные теаксономии (категории отзывов). Для этого мы создадим в теме файл taxonomy-testimonial_category.php.
Он будет выводить отзывы одной категории. Код файла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?php /* File for taxonomy testimonial_catgory */ get_header(); ?> <main class="container"> <div id="content"> <h2><?php single_cat_title() ?></h2> <?php $args = array( 'post_type' => 'testimonial', // Указываем наш новый тип записи 'posts_per_page' => 10, // количество выводимых постов 'tax_query' => array( // выбираем нужную категорию array( 'taxonomy' => 'testimonial_category', 'field' => 'slug', 'terms' => get_queried_object()->name )), ); $p = get_posts( $args ); foreach ( $p as $post ) { setup_postdata( $post ); // получаем данные каждого поста ?> <?php get_template_part( 'inc/one-testimonial' ); ?> <?php } wp_reset_postdata(); ?> </div><!--/#content--> </main><!-- /.container --> <?php get_sidebar('right'); get_footer(); |
Здесь мы также используем файл из папки inc, но уже с названием one-testimonial.php. Его код похож на код файла testimonial.php, но без ссылки на категорию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <div class="testimonial-block"> <div class="testimonial-text"> <?php the_content(); ?> </div><!-- /testimonial-text --> <div class="flex-row"> <div class="testimonial-teacher"> <p>Преподаватель:</p> <?php echo get_post_meta(get_the_ID(), 'teacher_name', true); ?></div> <div class="testimonial-title flex-row"> <?php if(has_post_thumbnail()){ the_post_thumbnail( 'thumbnail', ['class'=>'img-circle'] ); } ?> <div class="author"> <p>Автор:</p> <?php the_title(); ?> </div> </div> </div> </div> |
Если у вас нет необходимости в выводе ссылки на категорию для одного отзыва, то выводить вы будете один и тот же файл.
Шаг 6. Файлы переводов
Поскольку мы писали код преимущественно на английском языке, а сайт у нас может быть на любом языке, то нам необходимо создать файл перевода. Для этого можно использовать программу PoEdit. Файлы перевода сохраняются в папку languages, которая должна быть в вашей теме.
Переводу подлежат все строки, который были "обернуты" в специальные функции WordPress __('Testimonials', 'theme-name' )
(если не предполагается сразу вывод информации), или _e( 'Teacher Name', 'theme-name' );
, если нужно выводить соответствующий текст в теме. 'theme-name'
- это название вашей темы, которое также указывается в файле functions.php темы в строке load_theme_textdomain( 'theme-name', THEME_DIR . '/languages' );.
Эти функции PoEdit находит и собирает в файл, который затем сохраняется с расирением .pot и названием вашей темы.
Каждую строку в этом файле затем нужно выделить первести в специальном поле в самом низу. Когда все строки переведены, сохраняем файл с расширением .po и названием языка.
Теперь можно еще раз посмотреть на то, как отображаются записи типа Testimonials в админке WordPress. Если все сделано верно, то все англоязычные названия поменяются на те, что были в вашем переводе.
Создаете свои темы и кастомизируете их? Возможно, вам будет интересен и процесс создания плагина.