Что такое Custom Post Type и зачем нужны дополнительные метаданные
В WordPress существуют стандартные типы записей, такие как посты и страницы, но часто для удобства организации контента требуется создавать собственные типы записей — Custom Post Type (CPT). CPT позволяют структурировать сайт под конкретные задачи, например, создавать раздел с отзывами, портфолио, каталогом товаров и т.д.
Однако просто создать CPT недостаточно — обычно необходимо добавить дополнительные поля (метаданные), чтобы хранить специфичную информацию, например, рейтинг, дату события, дополнительное описание и т.п. Это значительно расширяет функциональность сайта и упрощает работу с контентом.
В этой статье я подробно расскажу, как правильно создавать Custom Post Type и добавлять к нему метаданные с сохранением безопасности и удобства использования.
Создание Custom Post Type в WordPress
Для регистрации CPT в WordPress используется функция register_post_type(). Регистрировать CPT нужно в хуке init, чтобы все загрузилось корректно.
Рассмотрим пример создания CPT «Отзывы» для сайта:
function wpbegin_register_reviews_cpt() {
$labels = [
'name' => 'Отзывы',
'singular_name' => 'Отзыв',
'add_new' => 'Добавить отзыв',
'add_new_item' => 'Добавить новый отзыв',
'edit_item' => 'Редактировать отзыв',
'new_item' => 'Новый отзыв',
'view_item' => 'Просмотреть отзыв',
'search_items' => 'Искать отзывы',
'not_found' => 'Отзывы не найдены',
'not_found_in_trash' => 'В корзине отзывы не найдены',
'menu_name' => 'Отзывы'
];
$args = [
'labels' => $labels,
'public' => true,
'has_archive' => true,
'rewrite' => ['slug' => 'reviews'],
'supports' => ['title', 'editor', 'thumbnail'],
'show_in_rest' => true, // для совместимости с Gutenberg
'menu_icon' => 'dashicons-testimonial'
];
register_post_type('wpbegin_reviews', $args);
}
add_action('init', 'wpbegin_register_reviews_cpt');После добавления этого кода в файл темы functions.php или в кастомный плагин, в админке появится новый тип записей «Отзывы».
Добавление дополнительных метаданных (Custom Fields) в CPT
Чтобы добавить дополнительные поля, нужно использовать метабоксы. Метабокс — это блок на странице редактирования записи, где можно вводить дополнительные данные.
Создадим метабокс для CPT «Отзывы», в котором будем хранить, например, имя автора отзыва и рейтинг.
Регистрация метабокса
function wpbegin_add_reviews_metabox() {
add_meta_box(
'wpbegin_reviews_meta',
'Дополнительные данные отзыва',
'wpbegin_reviews_meta_callback',
'wpbegin_reviews',
'normal',
'default'
);
}
add_action('add_meta_boxes', 'wpbegin_add_reviews_metabox');Вывод полей в метабоксе
function wpbegin_reviews_meta_callback($post) {
// Безопасность
wp_nonce_field('wpbegin_reviews_save_meta', 'wpbegin_reviews_meta_nonce');
// Получаем текущие значения метаданных
$author_name = get_post_meta($post->ID, '_wpbegin_author_name', true);
$rating = get_post_meta($post->ID, '_wpbegin_rating', true);
echo '<p><label for="wpbegin_author_name">Имя автора:</label><br>';
echo '<input type="text" id="wpbegin_author_name" name="wpbegin_author_name" value="' . esc_attr($author_name) . '" size="25" /></p>';
echo '<p><label for="wpbegin_rating">Рейтинг (1-5):</label><br>';
echo '<input type="number" id="wpbegin_rating" name="wpbegin_rating" value="' . esc_attr($rating) . '" min="1" max="5" /></p>';
}Сохранение метаданных
function wpbegin_save_reviews_meta($post_id) {
// Проверяем nonce
if (!isset($_POST['wpbegin_reviews_meta_nonce']) || !wp_verify_nonce($_POST['wpbegin_reviews_meta_nonce'], 'wpbegin_reviews_save_meta')) {
return;
}
// Проверяем права пользователя
if (!current_user_can('edit_post', $post_id)) {
return;
}
// Проверяем автосохранение
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// Сохраняем имя автора
if (isset($_POST['wpbegin_author_name'])) {
update_post_meta($post_id, '_wpbegin_author_name', sanitize_text_field($_POST['wpbegin_author_name']));
}
// Сохраняем рейтинг
if (isset($_POST['wpbegin_rating'])) {
$rating = intval($_POST['wpbegin_rating']);
if ($rating >= 1 && $rating <= 5) {
update_post_meta($post_id, '_wpbegin_rating', $rating);
} else {
delete_post_meta($post_id, '_wpbegin_rating');
}
}
}
add_action('save_post', 'wpbegin_save_reviews_meta');Вывод Custom Post Type с метаданными на фронтенде
Чтобы вывести отзывы со всеми метаданными на сайте, можно создать кастомный шаблон или использовать WP_Query. Вот пример запроса и вывода:
$args = [
'post_type' => 'wpbegin_reviews',
'posts_per_page' => 10
];
$reviews = new WP_Query($args);
if ($reviews->have_posts()) {
echo '<ul class="wpbegin-reviews-list">';
while ($reviews->have_posts()) {
$reviews->the_post();
$author = get_post_meta(get_the_ID(), '_wpbegin_author_name', true);
$rating = get_post_meta(get_the_ID(), '_wpbegin_rating', true);
echo '<li><h3>' . get_the_title() . '</h3>';
echo '<p>' . get_the_content() . '</p>';
echo '<p><strong>Автор:</strong> ' . esc_html($author) . '</p>';
echo '<p><strong>Рейтинг:</strong> ' . intval($rating) . ' / 5</p></li>';
}
echo '</ul>';
wp_reset_postdata();
} else {
echo '<p>Отзывы не найдены.</p>';
}Этот код можно вставить в шаблон темы или в шорткод для использования в любом месте сайта.
Примеры полезных плагинов для работы с Custom Post Type и метаданными
Если хочется упростить задачу и использовать визуальный интерфейс для создания CPT и метаполей, рекомендую обратить внимание на следующие плагины:
- Advanced Custom Fields (ACF) — мощный инструмент для создания и управления метаполями с множеством типов полей.
- Custom Post Type UI — облегчает регистрацию Custom Post Type и таксономий без кода.
- Meta Box — расширенный плагин для создания метабоксов и полей с большим набором опций.
Использование этих плагинов не отменяет знания основ кода, но заметно ускоряет разработку и управление контентом.
Безопасность и производительность при работе с метаданными
При добавлении метаданных важно соблюдать несколько правил безопасности:
- Используйте
wp_nonce_fieldи проверяйте nonce при сохранении, чтобы защитить формы от CSRF. - Проверяйте права пользователя через
current_user_can(), чтобы не позволять изменять данные неавторизованным. - Санитизируйте входящие данные — например,
sanitize_text_field()для текстовых полей,intval()для чисел.
Также избегайте избыточного количества метаполей и сложных запросов с метаданными, так как это может замедлить работу сайта. В некоторых случаях лучше кэшировать результаты или использовать специализированные таблицы.