В тех случаях, когда информация общая для нескольких записей (постов), удобно использовать общее произвольное поле.
Такое произвольное поле позволит выводить одну и ту же информацию на нескольких страницах сайта. В том числе, при редактировании записей будут видны общие поля. Также при редактировании в каждой из записей можно вносить изменения в произвольные поля всех общих страниц.
Возможно где-то похожее уже реализовано, но я ничего подобного не видел. И ничего не найдя пришлось делать самому.
За основу взят код с сайта wp-kama.ru.
I. Создаём 3 дополнительных произвольных поля
В первом поле (mainPostId) будет содержаться ID записи, в котором будем хранить общие данные. Для этой цели (для общих данных) можно использовать ID первой записи.
Второе поле (fieldBelongOtherPost) будет показываться в том случае, когда заполнено первое поле – mainPostId. Это необходимо, чтобы случайно не перезаписать данные основного поста, когда содержимое на страницу ещё не передаётся. Если этого не сделать, можно перезаписать основной пост пустыми данными.
Третье поле (fieldCurrentPost) будет показывать содержимое текущего поста. На тот случай, если это главная запись. Или мы захотим сделать её главной.
Всегда показывается либо второе либо третье поле, чтобы не дублировалась информация в админке и не приводила к путанице.
Код для создания произвольных полей:
add_meta_box(
'mainPostId',
'Id главной записи',
'mainPostId', 'post', 'normal', 'low'
);
global $post;
$mainPostId = get_post_meta($post->ID, 'main_post_id', true);
if ($mainPostId) {
add_meta_box(
'fieldBelongOtherPost',
'Содержимое из полей главной записи',
'fieldBelongOtherPost', 'post', 'normal', 'low'
);
} else {
add_meta_box(
'fieldCurrentPost',
'Содержимое текущей записи',
'fieldCurrentPost', 'post', 'normal', 'low'
);
}
}
add_action('add_meta_boxes', 'my_extra_fields', 1);
II. Подключение произвольных полей
Далее, в этом же файле ниже, подключаем стили. Это можно сделать как через php файл, так и вынести отдельно в css. У меня это сделано через php, потому что изначально все было в одном файле, пока серьёзно не разрослось. И некогда было всё это переносить в отдельный css файл.
Теперь подключаем основной файл с произвольным полем:
Удобно подключать свои произвольные поля через отдельные файлы. Со временем, добавляя всё новые произвольные поля, если они находятся в одном файле, это усложняет нахождение и добавление нового содержимого.
Ну и собственно сам код:
function mainPostId($post) {
global $post;
$mainPostId = get_post_meta($post->ID, 'main_post_id', true);
?>
<div class="box-row">
<div class="row-1">
<label for="main_post_id">ID главной записи
<?php if ($mainPostId) { ?>
– <a target="_blank"
href="<?php echo esc_url(home_url()); ?>/wp-admin/post.php?post=<?php
echo $mainPostId ?>&action=edit">
<?php echo get_the_title($mainPostId); ?>
</a>
<?php } ?>
</label>
</div>
<div class="row-2">
<input type="text" id="main_post_id" name="extra[main_post_id]"
value="<?php echo get_post_meta($post->ID, 'main_post_id', 1); ?>"
>
</div>
</div>
<input type="hidden" name="extra_fields_nonce" value="<?php echo wp_create_nonce('mcf'); ?>" />
<?php
}
/* = Данные из главной записи
--------------------------------------- */
function fieldBelongOtherPost($post){
global $post;
$mainPostId = get_post_meta($post->ID, 'main_post_id', true);
?>
<div class="box-textarea">
<div class="textarea-1"><label for="commonData2">Основная линия</label></div>
<?php
// Выводим содержимое этого поста
wp_editor(get_post_meta($mainPostId, 'common_data', 1), 'commonData2',
[
'textarea_name' => 'for_main_post[common_data]',
'media_buttons' => 0,
'textarea_rows' => 5,
'editor_class' => 'editor-class',
'drag_drop_upload' => false,
'quicktags' => [
'buttons' => 'link'
],
]);
?>
</div>
<input type="hidden" name="for_main_post_fields_nonce" value="<?php echo wp_create_nonce('mcf'); ?>" />
<?php
}
/* = Данные текущей записи
--------------------------------------- */
function fieldCurrentPost($post) {
?>
<div class="box-textarea">
<div class="textarea-1"><label for="commonData">Основная информация</label></div>
<?php
wp_editor(get_post_meta($post->ID, 'common_data', 1), 'commonData',
[
'textarea_name' => 'extra[common_data]',
'media_buttons' => 0,
'textarea_rows' => 5,
'editor_class' => 'editor-class',
'drag_drop_upload' => false,
'quicktags' => [
'buttons' => 'link'
],
]);
?>
</div>
<input type="hidden" name="extra_fields_nonce" value="<?php echo wp_create_nonce('mcf'); ?>" />
<?php
}
Вот как общие поля выглядят в админке:
III. Функционал для сохранения данных их произвольных полей
Теперь это дело нужно сохранить. В сохранении у нас участвуют две функции. Первая сохраняет свои произвольные поля для текущей записи. Вторая функция сохраняет произвольные поля для основной записи.
--------------------------------------- */
function my_extra_fields_update($currentPostId){
// Проверяем есть ли nonce
if (!isset($_POST['extra_fields_nonce'])) return false;
// Выключил. Не работает при include файла.
// if (!wp_verify_nonce($_POST['my_extra_fields'], 'mcf')) return false;
// Отменяем для автосохранения
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return false;
// Проверяем имеет ли юзер право редактировать ГЛАВНУЮ запись
if (!current_user_can('edit_post', $currentPostId)) return false;
// Проверяем есть ли отправляемые значения
if (!isset($_POST['extra'])) return false;
// Все ОК! Теперь, нужно сохранить/удалить данные
$_POST['extra'] = array_map('trim', $_POST['extra']);
foreach($_POST['extra'] as $k => $v){
// Удаляем поле если значение пустое
if(empty($v)){
delete_post_meta($currentPostId, $k);
continue;
}
update_post_meta($currentPostId, $k, $v); // add_post_meta() работает автоматически
}
return $currentPostId;
}
add_action('save_post', 'my_extra_fields_update', 0);
/* = Сохранении полей для ВНЕШНЕЙ (другой) записи
--------------------------------------- */
function update_post_meta_for_main_post($currentPostId){
// Получаем ID главного поста (если оно заполнено на странице)
global $post;
$mainPostId = get_post_meta($post->ID, 'movie_series_id', true);
// Проверяем есть ли nonce
if (!isset($_POST['for_main_post_fields_nonce'])) return false;
// Выключил. Не работает при include файла.
// if (!wp_verify_nonce($_POST['for_main_post_fields_nonce'], 'mcf')) return false;
// Отменяем для автосохранения
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return false;
// Проверяем имеет ли юзер право редактировать ГЛАВНУЮ запись
if (!current_user_can('edit_post', $mainPostId)) return false;
// Проверяем есть ли отправляемые значения
if (!isset($_POST['for_main_post'])) return false;
// Все ОК! Теперь, нужно сохранить/удалить данные
$_POST['for_main_post'] = array_map('trim', $_POST['for_main_post']);
foreach($_POST['for_main_post'] as $k => $v){
// Удаляем поле если значение пустое
if (empty($v)){
delete_post_meta($mainPostId, $k);
continue;
}
update_post_meta($mainPostId, $k, $v); // add_post_meta() работает автоматически
}
return $currentPostId;
}
add_action('save_post', 'update_post_meta_for_main_post', 0);
IV. Выводим общее содержимое на странице single
Теперь всё готово. Осталось вывести данные на странице записей:
// Получаем в переменную ID главной записи
$mainPostId = get_post_meta($post->ID, 'main_post_id_id', true);
// Вывод содержимого главной записи
if ($mainPostId) {
?>
<section class="signle-section">
<h3 class="title-section"><?php echo __( 'Общие данные', 'ploshadka' ); ?></h3>
<?php if (get_post_meta($mainPostId, 'main_post_id', true) ) : ?>
<div class="ploshadka.net">
<?php echo get_post_meta($mainPostId, 'main_post_id', true); ?>
</div>
<?php endif; ?>
</section>
<?php
// Вывод содержимого текущей записи
} elseif (get_post_meta($post->ID, 'main_post_id', true) ) { ?>
<section class="signle-section">
<h3 class="title-section"><?php echo __( 'Общие данные', 'ploshadka' ); ?></h3>
<?php if (get_post_meta($post->ID, 'main_post_id', true) ) : ?>
<div class="ploshadka.net">
<?php echo get_post_meta($post->ID, 'main_post_id', true); ?>
</div>
<?php endif; ?>
</section>
<?php } ?>