Когда вы разрабатываете тему или плагин, иногда возникает необходимость добавить некий функционал, который должен существовать помимо стандартного, реализованного в WordPress "из коробки", а именно записей и страниц. С одной стороны, такой функционал можно добавить с помощью плагинов, с другой - не всегда тот вариант отображения информации, который предлагается разработчиками плагинов, устраивает именно вас.В этом случае на помощь приходит возможность добавить в WordPress свои, пользовательские, или кастомные типы записей, которые будут решать те задачи, которые важны прежде всего для вас.
В этой статье мы будем создавать пользовательские типы записей, связанные с отзывами. Это достаточно популярный элемент любого сайта, продающего товары или услуги.
- Шаг 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'); |
А теперь внимание - есть еще один подвох, выделенный в коде выше. Он говорит о том, что данный тип записи (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. Если все сделано верно, то все англоязычные названия поменяются на те, что были в вашем переводе.