Если логотип, телефон и ссылки темы приходится менять в коде, удобнее собрать их на отдельной странице админки. В WordPress для этого есть Settings API: он создаёт форму, сохраняет значения и применяет стандартные проверки безопасности. Ниже — пример страницы в разделе «Внешний вид» с полями для логотипа, телефона, email и ссылки.
Код добавьте в functions.php дочерней темы, а не родительской: при обновлении родительской темы её файлы могут быть заменены. Если настройки должны оставаться доступными после смены темы, разместите функциональность в собственном плагине. Пример использует обычные функции WordPress и не требует сторонних плагинов.
Создаём страницу и регистрируем настройки
Добавьте следующий код. Префикс mytheme_ замените на уникальный для вашей темы: это снизит риск конфликта с другим кодом сайта. Страница появится в меню «Внешний вид» у пользователей с правом edit_theme_options.
add_action( 'admin_menu', 'mytheme_add_settings_page' );
function mytheme_add_settings_page() {
add_theme_page(
'Настройки темы',
'Настройки темы',
'edit_theme_options',
'mytheme-settings',
'mytheme_render_settings_page'
);
}
add_action( 'admin_init', 'mytheme_register_settings' );
function mytheme_register_settings() {
register_setting(
'mytheme_settings_group',
'mytheme_options',
array( 'sanitize_callback' => 'mytheme_sanitize_options' )
);
add_settings_section(
'mytheme_main_section',
'Основные данные',
'mytheme_settings_section_text',
'mytheme-settings'
);
add_settings_field( 'mytheme_logo', 'Логотип', 'mytheme_logo_field', 'mytheme-settings', 'mytheme_main_section' );
add_settings_field( 'mytheme_phone', 'Телефон', 'mytheme_phone_field', 'mytheme-settings', 'mytheme_main_section' );
add_settings_field( 'mytheme_email', 'Email', 'mytheme_email_field', 'mytheme-settings', 'mytheme_main_section' );
add_settings_field( 'mytheme_social_url', 'Ссылка на страницу', 'mytheme_social_url_field', 'mytheme-settings', 'mytheme_main_section' );
}
function mytheme_sanitize_options( $input ) {
if ( ! is_array( $input ) ) {
return array();
}
return array(
'logo_id' => isset( $input['logo_id'] ) ? absint( $input['logo_id'] ) : 0,
'phone' => isset( $input['phone'] ) ? sanitize_text_field( $input['phone'] ) : '',
'email' => isset( $input['email'] ) ? sanitize_email( $input['email'] ) : '',
'social_url' => isset( $input['social_url'] ) ? esc_url_raw( $input['social_url'] ) : '',
);
}
function mytheme_settings_section_text() {
echo '<p>Укажите данные, которые используются в шапке или подвале сайта.</p>';
}
function mytheme_render_settings_page() {
?>
<div class="wrap">
<h1>Настройки темы</h1>
<form action="options.php" method="post">
<?php
settings_fields( 'mytheme_settings_group' );
do_settings_sections( 'mytheme-settings' );
submit_button();
?>
</form>
</div>
<?php
}add_theme_page() создаёт пункт в «Внешний вид», а register_setting() связывает группу формы с опцией mytheme_options. Форма выводит обязательные служебные поля через settings_fields(); не удаляйте этот вызов — он, в частности, добавляет nonce для проверки отправки. Значения всех полей хранятся вместе в одном массиве. Функция очистки приводит каждый элемент к ожидаемому типу: идентификатор изображения — к целому числу, текст — к безопасной строке, URL — к безопасному адресу.
Добавляем поля и выбор логотипа
К тем же функциям добавьте обработчики полей. Для логотипа используется медиабиблиотека WordPress: в настройке сохраняется ID вложения, а не введённый вручную адрес файла.
function mytheme_get_options() {
$options = get_option( 'mytheme_options', array() );
return is_array( $options ) ? $options : array();
}
function mytheme_logo_field() {
$options = mytheme_get_options();
$logo_id = isset( $options['logo_id'] ) ? absint( $options['logo_id'] ) : 0;
?>
<input type="hidden" id="mytheme-logo-id" name="mytheme_options[logo_id]" value="<?php echo esc_attr( $logo_id ); ?>">
<div id="mytheme-logo-preview"><?php if ( $logo_id ) { echo wp_get_attachment_image( $logo_id, 'thumbnail' ); } ?></div>
<button type="button" class="button" id="mytheme-select-logo">Выбрать логотип</button>
<button type="button" class="button" id="mytheme-remove-logo">Убрать</button>
<?php
}
function mytheme_phone_field() {
$options = mytheme_get_options();
printf( '<input class="regular-text" type="text" name="mytheme_options[phone]" value="%s">', esc_attr( $options['phone'] ?? '' ) );
}
function mytheme_email_field() {
$options = mytheme_get_options();
printf( '<input class="regular-text" type="email" name="mytheme_options[email]" value="%s">', esc_attr( $options['email'] ?? '' ) );
}
function mytheme_social_url_field() {
$options = mytheme_get_options();
printf( '<input class="regular-text" type="url" name="mytheme_options[social_url]" value="%s">', esc_attr( $options['social_url'] ?? '' ) );
}
add_action( 'admin_enqueue_scripts', 'mytheme_settings_media' );
function mytheme_settings_media( $hook_suffix ) {
if ( 'appearance_page_mytheme-settings' !== $hook_suffix ) {
return;
}
wp_enqueue_media();
wp_enqueue_script( 'jquery' );
$script = <<<'JS'
jQuery(function($) {
var frame;
$('#mytheme-select-logo').on('click', function(event) {
event.preventDefault();
if (frame) {
frame.open();
return;
}
frame = wp.media({
title: 'Выберите логотип',
button: { text: 'Использовать логотип' },
multiple: false,
library: { type: 'image' }
});
frame.on('select', function() {
var image = frame.state().get('selection').first().toJSON();
$('#mytheme-logo-id').val(image.id);
$('#mytheme-logo-preview').html('<img src="' + image.url + '" alt="" style="max-width:180px;height:auto;">');
});
frame.open();
});
$('#mytheme-remove-logo').on('click', function(event) {
event.preventDefault();
$('#mytheme-logo-id').val('0');
$('#mytheme-logo-preview').empty();
});
});
JS;
wp_add_inline_script( 'jquery', $script );
}Проверка $hook_suffix нужна, чтобы загружать медиабиблиотеку и JavaScript только на странице настроек. Если измените slug mytheme-settings в add_theme_page(), обновите и проверяемое значение: для страницы в разделе «Внешний вид» WordPress формирует hook в виде appearance_page_ плюс slug.
Выводим сохранённые значения в теме
Сохранение настройки само по себе не меняет сайт: шаблон темы должен получить значения и вывести их в нужном месте. Например, в файле шапки можно использовать такой код:
<?php
$options = get_option( 'mytheme_options', array() );
$options = is_array( $options ) ? $options : array();
if ( ! empty( $options['logo_id'] ) ) {
echo wp_get_attachment_image( absint( $options['logo_id'] ), 'full', false, array( 'class' => 'site-logo' ) );
}
if ( ! empty( $options['phone'] ) ) {
echo '<p>' . esc_html( $options['phone'] ) . '</p>';
}
if ( ! empty( $options['email'] ) ) {
echo '<p>' . esc_html( $options['email'] ) . '</p>';
}
if ( ! empty( $options['social_url'] ) ) {
echo '<a href="' . esc_url( $options['social_url'] ) . '">Наша страница</a>';
}
?>Вставляйте этот фрагмент в подходящий шаблон, например в файл шапки дочерней темы. Если телефон нужен как ссылка для звонка, оформите его отдельно: для атрибута href="tel:..." понадобится подготовить номер без пробелов и скобок. При выводе текстовых значений используйте экранирование, соответствующее контексту: esc_html() для текста, esc_url() для адреса ссылки, esc_attr() для HTML-атрибутов.
Проверяем страницу и сохраняем данные
Откройте в админке «Внешний вид → Настройки темы», выберите изображение, заполните поля и нажмите «Сохранить изменения». После перезагрузки проверьте, что выбранный логотип и введённые значения остались в форме. Затем откройте страницу сайта, в шаблон которой добавлен код вывода.
Если пункта меню нет, проверьте, что код загрузился без PHP-ошибки, текущий пользователь имеет право edit_theme_options, а код страницы и функции регистрации подключены в активной теме. Если данные сохраняются, но не появляются на сайте, проверьте имя опции и ключи массива в шаблоне: в этом примере это mytheme_options, logo_id, phone, email и social_url.
Опция, созданная через register_setting(), сохраняется в базе WordPress и не удаляется при выключении темы. Но страница админки и код вывода перестанут работать, если отключить тему, в которой они находятся. Для темы, предназначенной для распространения, замените общий префикс на уникальный и не меняйте его между версиями: иначе настройки будут сохранены под старым именем и новая версия их не найдёт.