Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Произвольные поля

У книги есть цена и число страниц, у события — дата и место, у вакансии — зарплата. Такие данные не помещаются в заголовок и текст. WordPress хранит их в метаданных — парах «ключ — значение», привязанных к записи.

Чтение и запись

update_post_meta($postId, 'book_price', 450);
 
$price = get_post_meta($postId, 'book_price', true);
 
delete_post_meta($postId, 'book_price');

Третий аргумент get_post_meta() — true — возвращает одно значение. Без него функция вернёт массив: под одним ключом может храниться несколько значений.

Вывод в шаблоне

<?php
// single-book.php
 
$price = get_post_meta(get_the_ID(), 'book_price', true);
$pages = get_post_meta(get_the_ID(), 'book_pages', true);
 
if ($price !== '') {
    echo '<p class="price">' . esc_html(number_format((float) $price, 0, ',', ' ')) . ' ₽</p>';
}
 
if ($pages !== '') {
    echo '<p>Страниц: ' . (int) $pages . '</p>';
}

Если поля нет, функция возвращает пустую строку.

Поле в редакторе

Чтобы редактор мог вводить цену, в форму записи добавляют блок:

// books.php
 
add_action('add_meta_boxes', function () {
    add_meta_box('book_details', 'Сведения о книге', 'books_render_details', 'book', 'side');
});
 
function books_render_details(WP_Post $post): void
{
    wp_nonce_field('book_details', 'book_details_nonce');
 
    $price = get_post_meta($post->ID, 'book_price', true);
    ?>
    <label for="book_price">Цена, ₽</label>
    <input type="number" id="book_price" name="book_price" value="<?php echo esc_attr($price); ?>" min="0">
    <?php
}

wp_nonce_field() добавляет скрытое поле с токеном — он понадобится при сохранении.

Сохранение

// books.php
 
add_action('save_post_book', function (int $postId) {
    if (!isset($_POST['book_details_nonce'])
        || !wp_verify_nonce($_POST['book_details_nonce'], 'book_details')) {
        return;
    }
 
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
 
    if (!current_user_can('edit_post', $postId)) {
        return;
    }
 
    update_post_meta($postId, 'book_price', absint($_POST['book_price'] ?? 0));
});

Три проверки: токен настоящий, это не автосохранение, у пользователя есть право менять запись. Значение приводится к целому числу функцией absint().

Поля в REST API

Чтобы поле было доступно блочному редактору и API, его регистрируют:

add_action('init', function () {
    register_post_meta('book', 'book_price', [
        'type' => 'integer',
        'single' => true,
        'show_in_rest' => true,
        'sanitize_callback' => 'absint',
    ]);
});

Готовый плагин

Для сайтов с десятками полей пользуются плагином Advanced Custom Fields: поля создают в панели, а в шаблоне читают функцией get_field('book_price'). Данные при этом лежат в тех же метаданных.

Поиск по полям

Записи можно отбирать и сортировать по значению поля — об этом в следующем уроке о WP_Query.

Частая ошибка

Обработчик save_post без проверок — уязвимость: любой запрос с нужным полем изменит данные чужой записи. Всегда проверяйте токен функцией wp_verify_nonce(), права функцией current_user_can() и очищайте значение перед записью — absint(), sanitize_text_field(), sanitize_email().

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.