Создание пользовательских страниц в панели управления WordPress

Раздел: Системы управления контентом -> CMS WordPress

Создание страниц админки в WordPress с помощью PHP

Наиболее эффективный способ добавления собственных страниц в панель управления WordPress - использование функций add_menu_page и add_submenu_page. Эти функции регистрируют пункты меню и связывают их с функциями отображения контента. Пример базового подхода:

add_action('admin_menu', 'my_custom_admin_page');
function my_custom_admin_page() {
    add_menu_page(
        'Заголовок страницы',
        'Название меню',
        'manage_options',
        'my-plugin-slug',
        'my_admin_page_display',
        'dashicons-admin-generic',
        30
    );
}
function my_admin_page_display() {
    ?>
    <div class="wrap">
        <h1>Моя страница админки</h1>
        <p>Содержимое страницы.</p>
    </div>
    <?php
}

Function php wp (функции wordpress php)

Параметры: заголовок страницы (в теге <title>), название пункта меню, необходимые права (capability), уникальный slug, функция обратного вызова, иконка (можно передавать URL или dashicon), позиция в меню. После этого страница становится доступна в боковом меню.

Типичные ошибки:

  • Неправильный slug - приводит к тому, что страница не отображается или конфликтует с другими плагинами.
  • Отсутствие хука admin_menu - без него функции регистрации не сработают.
  • Использование неверной capability - пользователь без прав не увидит пункт меню.
  • Забытая директива ?> в начале HTML - приводит к синтаксической ошибке.

Как добавить страницу настроек с использованием Settings API?

Создание страницы настроек, которая автоматически сохраняет данные в таблицу wp_options с помощью Settings API. Пример:

add_action('admin_menu', 'my_settings_page');
function my_settings_page() {
    add_options_page(
        'Настройки плагина',
        'Мой плагин',
        'manage_options',
        'my-plugin-settings',
        'my_settings_page_display'
    );
}
add_action('admin_init', 'my_register_settings');
function my_register_settings() {
    register_setting('my_settings_group', 'my_option_name');
    add_settings_section(
        'my_section',
        'Основной раздел',
        'my_section_callback',
        'my-plugin-settings'
    );
    add_settings_field(
        'my_field',
        'Текстовое поле',
        'my_field_callback',
        'my-plugin-settings',
        'my_section'
    );
}

Php woocommerce content (работа с контентом woocommerce в php)

Проблемы:

  • Несовпадение slug страницы и slug секции - настройки не отображаются.
  • Отсутствие вызова settings_fields() и do_settings_sections() в форме - данные не сохраняются.
  • Игнорирование nonce - уязвимость CSRF.

Как создать страницу с кастомной таблицей данных на основе WP_List_Table?

Для отображения списков записей (например, из произвольной таблицы БД) удобно наследовать класс WP_List_Table. Пример:

if (!class_exists('WP_List_Table')) {
    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}
class My_Custom_Table extends WP_List_Table {
    function get_columns() {
        return ['cb' => '<input type="checkbox" />', 'name' => 'Имя', 'email' => 'Email'];
    }
    function prepare_items() {
        $this->items = [
            ['name' => 'Иван', 'email' => 'ivan@example.com'],
            ['name' => 'Петр', 'email' => 'petr@example.com']
        ];
    }
    function column_default($item, $column_name) {
        return $item[$column_name];
    }
}

Admin pages php (страницы админки на php)

Вывод таблицы на странице админки:

$table = new My_Custom_Table();
$table->prepare_items();
$table->display();

Wp themes php (темы wordpress на php)

Ошибки:

  • Отсутствие обработки bulk-действий - таблица не реагирует на массовые операции.
  • Неправильная установка колонок и сортировка - данные отображаются хаотично.
  • Игнорирование пагинации - при большом количестве записей всё грузится медленно.

Как создать страницу админки с использованием ООП (класса)?

Объектно-ориентированный подход улучшает читаемость и повторное использование кода. Пример класса, который регистрирует страницу:

class My_Admin_Page {
    public function __construct() {
        add_action('admin_menu', [$this, 'add_admin_menu']);
    }
    public function add_admin_menu() {
        add_menu_page(
            'ООП страница',
            'Мой класс',
            'manage_options',
            'my-oop-page',
            [$this, 'render_page'],
            'dashicons-admin-site',
            25
        );
    }
    public function render_page() {
        echo '<div class="wrap"><h1>Привет из ООП</h1></div>';
    }
}
new My_Admin_Page();

Проблемы:

  • Несовместимость с PHP 5.2 - использование коротких массивов и анонимных функций.
  • Множественные экземпляры класса - повторная регистрация меню.
  • Отсутствие автозагрузки - класс не найден до хука.

Как добавить страницу в существующее меню (например, Инструменты)?

Для добавления подменю к стандартным разделам используют add_submenu_page с указанием родительского slug. Пример для «Инструменты»:

add_action('admin_menu', 'my_tools_page');
function my_tools_page() {
    add_submenu_page(
        'tools.php',
        'Мой инструмент',
        'Мой инструмент',
        'manage_options',
        'my-tools',
        'my_tools_page_callback'
    );
}

Ошибка: неверный родительский slug (например, 'tools' вместо 'tools.php') - пункт меню не появляется.

Как ограничить доступ к странице по ролям пользователей?

Используйте параметр capability. Для сложных проверок применяйте фильтр user_has_cap или кастомные capability. Пример:

add_action('admin_menu', 'my_role_based_page');
function my_role_based_page() {
    if (current_user_can('editor') || current_user_can('administrator')) {
        add_menu_page(
            'Страница для редакторов',
            'Редакторский раздел',
            'edit_posts',
            'editor-page',
            'editor_page_callback'
        );
    }
}

Проблема: проверка на current_user_can до вызова add_menu_page приводит к тому, что пункт меню может не появиться у пользователя, но страница останется доступной по прямому URL. Лучше использовать capability в самой функции регистрации.

Расширенные примеры создания страниц админки

Пример 1: Полноценный плагин с двумя страницами (настройки и список записей)

Пример
<?php
/*
Plugin Name: Demo Admin Pages
*/

class Demo_Admin_Pages {
    public function __construct() {
        add_action('admin_menu', [$this, 'register_pages']);
        add_action('admin_init', [$this, 'register_settings']);
    }

    public function register_pages() {
        // Основная страница
        add_menu_page(
            'Демо плагин',
            'Демо',
            'manage_options',
            'demo-main',
            [$this, 'render_main'],
            'dashicons-admin-generic',
            20
        );
        // Подстраница - настройки
        add_submenu_page(
            'demo-main',
            'Настройки',
            'Настройки',
            'manage_options',
            'demo-settings',
            [$this, 'render_settings']
        );
    }

    public function register_settings() {
        register_setting('demo_settings_group', 'demo_text_option');
        add_settings_section('demo_section', 'Основные настройки', null, 'demo-settings');
        add_settings_field('demo_field', 'Текст', [$this, 'field_callback'], 'demo-settings', 'demo_section');
    }

    public function field_callback() {
        $value = get_option('demo_text_option', '');
        echo "<input type='text' name='demo_text_option' value='" . esc_attr($value) . "' />";
    }

    public function render_main() {
        ?>
        <div class="wrap">
            <h1>Главная страница демо</h1>
            <p>Здесь можно вывести произвольную информацию.</p>
        </div>
        <?php
    }

    public function render_settings() {
        ?>
        <div class="wrap">
            <h1>Настройки демо</h1>
            <form action="options.php" method="post">
                <?php settings_fields('demo_settings_group'); ?>
                <?php do_settings_sections('demo-settings'); ?>
                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }
}
new Demo_Admin_Pages();

Результат: в меню появятся пункты «Демо» и подпункт «Настройки». На странице настроек отображается текстовое поле, значение сохраняется в wp_options.

После активации плагина в боковом меню WordPress появляется новая секция.

Пример 2: Страница с таблицей данных из кастомной таблицы БД

Пример
global $wpdb;
$table_name = $wpdb->prefix . 'custom_data';
// Создание таблицы (выполняется однократно при активации)
function create_custom_table() {
    global $wpdb;
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}custom_data (
        id int(11) NOT NULL AUTO_INCREMENT,
        name varchar(100) NOT NULL,
        email varchar(100) NOT NULL,
        PRIMARY KEY (id)
    ) $charset_collate;";
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_custom_table');

// Класс для отображения таблицы
if (!class_exists('WP_List_Table')) {
    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}
class Custom_Data_Table extends WP_List_Table {
    function get_columns() {
        return ['cb' => '<input type="checkbox" />', 'name' => 'Имя', 'email' => 'Email'];
    }
    function prepare_items() {
        global $wpdb;
        $per_page = 10;
        $current_page = $this->get_pagenum();
        $total_items = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}custom_data");
        $this->set_pagination_args([
            'total_items' => $total_items,
            'per_page'    => $per_page
        ]);
        $offset = ($current_page - 1) * $per_page;
        $this->items = $wpdb->get_results(
            "SELECT name, email FROM {$wpdb->prefix}custom_data LIMIT $per_page OFFSET $offset",
            ARRAY_A
        );
    }
    function column_default($item, $column_name) {
        return esc_html($item[$column_name]);
    }
    function get_bulk_actions() {
        return ['delete' => 'Удалить'];
    }
}

// Страница админки
add_action('admin_menu', function() {
    add_menu_page('Данные', 'Данные', 'manage_options', 'custom-data', 'render_custom_data_page');
});
function render_custom_data_page() {
    $table = new Custom_Data_Table();
    $table->prepare_items();
    ?>
    <div class="wrap">
        <h1>Список данных</h1>
        <form method="post">
            <?php $table->display(); ?>
        </form>
    </div>
    <?php
}

Результат: страница «Данные» в админке содержит таблицу с записями из собственной таблицы БД, с пагинацией и чекбоксами.

При наличии записей в таблице wp_custom_data они отобразятся в виде таблицы с возможностью массового удаления.

Пример 3: Страница с обработкой AJAX-запросов

Пример
add_action('admin_menu', function() {
    add_menu_page('AJAX demo', 'AJAX demo', 'manage_options', 'ajax-demo', 'ajax_demo_page');
});
function ajax_demo_page() {
    ?>
    <div class="wrap">
        <h1>AJAX Demo</h1>
        <button id="ajax-button" class="button button-primary">Отправить AJAX запрос</button>
        <div id="ajax-response"></div>
    </div>
    <script>
        jQuery(document).ready(function($) {
            $('#ajax-button').click(function() {
                $.post(ajaxurl, {
                    action: 'my_ajax_action',
                    nonce: '<?php echo wp_create_nonce('my_ajax_nonce'); ?>'
                }, function(response) {
                    $('#ajax-response').html(response);
                });
            });
        });
    </script>
    <?php
}
add_action('wp_ajax_my_ajax_action', 'handle_my_ajax');
function handle_my_ajax() {
    check_ajax_referer('my_ajax_nonce', 'nonce');
    echo 'Сервер ответил: ' . date('H:i:s');
    wp_die();
}

Результат: на странице появляется кнопка, по нажатию выполняется AJAX-запрос к WordPress, ответ выводится в блок.

После клика на кнопку в контейнере появляется текущее время сервера.

Страницы админки на PHP - comments

En
Admin pages php (php)