Создадим блок в котором мы будем прописывать пару иконка + подпись. При этом мы можем создавать таких пар сколько угодно и менять их порядок.
Реализация в виде функций
// Регистрируем метабокс
function register_custom_pairs_meta_box() {
add_meta_box(
'custom_pairs_meta_box',
'Пары (иконка + текст)',
'custom_pairs_metabox_callback',
array('post', 'page'),
'normal',
'high'
);
}
add_action('add_meta_boxes', 'register_custom_pairs_meta_box');
// Вывод метабокса
function custom_pairs_metabox_callback( $post ) {
wp_nonce_field( basename( __FILE__ ), 'custom_pairs_nonce' );
// Получаем сохранённые данные
$custom_pairs = get_post_meta( $post->ID, '_custom_pairs', true );
if ( ! is_array( $custom_pairs ) ) {
$custom_pairs = array(); // Пусть пока массив пуст
}
?>
<table id="custom-pairs-table" style="width:100%; border-collapse: collapse;">
<thead>
<tr>
<th>Наименование (русское)</th>
<th>Наименование (латинское)</th>
<th></th>
</tr>
</thead>
<tbody>
<?php
// Если есть сохранённые пары, выводим их
if ( ! empty( $custom_pairs ) ) {
foreach ( $custom_pairs as $index => $pair ) {
$name = isset( $pair['name'] ) ? esc_attr( $pair['name'] ) : '';
$latin_name = isset( $pair['latin_name'] ) ? esc_attr( $pair['latin_name'] ) : '';
?>
<tr>
<td><input type="text" name="custom_pairs[<?php echo $index; ?>][name]" value="<?php echo $name; ?>" style="width:100%;"></td>
<td><input type="text" name="custom_pairs[<?php echo $index; ?>][latin_name]" value="<?php echo $latin_name; ?>" style="width:100%;"></td>
<td class="actions">
<!-- <button type="button" class="move-up">↑</button> -->
<!-- <button type="button" class="move-down">↓</button> -->
<!-- <button type="button" class="delete-btn">Удалить</button> -->
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
<button type="button" id="add-row">Добавить пару</button>
<script>
(function($) {
$(document).ready(function() {
// Функция обновления стрелок у всех строк
function updateArrowButtons() {
$('#custom-pairs-table tbody tr').each(function() {
var $tr = $(this);
// Удаляем старые стрелки, чтобы не дублировать
$tr.find('.move-up, .move-down, .delete-btn').remove();
// Вставляем кнопки "вверх" и "вниз"
$('<button type="button" class="move-up">↑</button>').prependTo($tr.find('td.actions'));
$('<button type="button" class="move-down">↓</button>').appendTo($tr.find('td.actions'));
// добавляем кнопку Удалить, если её ещё нет
$('<button type="button" class="delete-btn">Удалить</button>').appendTo($tr.find('td.actions'));
});
}
// Изначально установим стрелки и кнопки
updateArrowButtons();
// Обработчик добавления новой строки
$('#add-row').on('click', function() {
var index = $('#custom-pairs-table tbody tr').length;
var newRow = '<tr>' +
'<td><input type="text" name="custom_pairs[' + index + '][name]" style="width:100%;"></td>' +
'<td><input type="text" name="custom_pairs[' + index + '][latin_name]" style="width:100%;"></td>' +
'<td class="actions"></td>' +
'</tr>';
$('#custom-pairs-table tbody').append(newRow);
updateArrowButtons();
});
// Обработка удаления
$('#custom-pairs-table').on('click', '.delete-btn', function() {
$(this).closest('tr').remove();
renumberInputs();
updateArrowButtons();
});
// Обработка перемещения вверх
$('#custom-pairs-table').on('click', '.move-up', function() {
var row = $(this).closest('tr');
var prev = row.prev();
if (prev.length) {
row.insertBefore(prev);
renumberInputs();
updateArrowButtons();
}
});
// Обработка перемещения вниз
$('#custom-pairs-table').on('click', '.move-down', function() {
var row = $(this).closest('tr');
var next = row.next();
if (next.length) {
row.insertAfter(next);
renumberInputs();
updateArrowButtons();
}
});
// Переименовываем поля при перестановке
function renumberInputs() {
$('#custom-pairs-table tbody tr').each(function(index) {
$(this).find('input[name^="custom_pairs"]').each(function() {
var nameAttr = $(this).attr('name');
nameAttr = nameAttr.replace(/custom_pairs$$\d+$$/, 'custom_pairs[' + index + ']');
$(this).attr('name', nameAttr);
});
});
}
});
})(jQuery);
</script>
<?php
}
// Сохраняем данные
function save_custom_pairs_meta( $post_id ) {
if ( ! isset( $_POST['custom_pairs_nonce'] ) || ! wp_verify_nonce( $_POST['custom_pairs_nonce'], basename( __FILE__ ) ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['custom_pairs'] ) && is_array( $_POST['custom_pairs'] ) ) {
$custom_pairs = $_POST['custom_pairs'];
$filtered_pairs = array();
foreach ( $custom_pairs as $pair ) {
$name = isset( $pair['name'] ) ? trim( $pair['name'] ) : '';
$latin_name = isset( $pair['latin_name'] ) ? trim( $pair['latin_name'] ) : '';
if ( empty( $name ) && empty( $latin_name ) ) {
continue; // пропускаем пустые
}
$filtered_pairs[] = array(
'name' => $name,
'latin_name' => $latin_name,
);
}
if ( ! empty( $filtered_pairs ) ) {
update_post_meta( $post_id, '_custom_pairs', $filtered_pairs );
} else {
delete_post_meta( $post_id, '_custom_pairs' );
}
} else {
delete_post_meta( $post_id, '_custom_pairs' );
}
}
add_action( 'save_post', 'save_custom_pairs_meta' );
Пример, как это выглядит в админке

Вывод данного поля
<?php $pairs = get_post_meta( $post->ID, '_custom_pairs', true );
foreach ($pairs as $index => $pair): ?>
<div class="item feat" title="<?php echo $pair['name']; ?>"><div>
<svg xmlns="http://www.w3.org/2000/svg"><use xlink:href="#<?php echo $pair['latin_name']; ?>"></use></svg>
<p><?php echo $pair['name']; ?></p>
</div></div>
<?php endforeach; ?>
Иконки подключается в подвале в виде отдельного файла.
[site-socialshare]

