add_menu_page()WP 1.5.0

Добавляет пункт (страницу) верхнего уровня в меню админ-панели (в один ряд с постами, страницами, пользователями и т.д.).

Используется для создания главного пункта меню в админ-панели и прикрепления к этому пункту функции, которая будет отвечать за страницу в админ-панели связанную с этим пунктом меню.

Нужно вызывать через один из хуков:

  • network_admin_menu — чтобы добавить в меню мультисайт.
  • admin_menu — обычное административное меню.

Если нужно добавить дочерний пункт меню, используйте add_submenu_page().

Если вы видите ошибку "You do not have sufficient permissions to access this page." при попытке зайти на страницу, это значит, что вы подключаете функцию слишком рано.

Подключать функцию нужно на хуке admin_menu.

Заметки

  1. Функция проверяет права пользователя, чтобы отобразить пункт меню и открыть доступ к странице этого пункта меню.

  2. Если используете API настроек для сохранения данных и нужно чтобы сохранение работало для пользователей с правами ниже администратора, вам нужно изменить разрешение через хук option_page_capability_{$option_page}, где $option_page должно быть равно параметру $menu_slug.

    Пример, как разрешить Редакторам (Editor) сохранять данные:

    add_action( 'admin_menu', 'register_my_page' );
    add_filter( 'option_page_capability_'.'my_page_slug', 'my_page_capability' );
    
    // Добавим видимость пункта меню для Редакторов
    function register_my_page(){
    	add_menu_page( 'My Page Title', 'My Page', 'edit_others_posts', 'my_page_slug', 'my_page_function', plugins_url( 'myplugin/images/icon.png' ), 6 );
    }
    
    // Изменим права
    function my_page_capability( $capability ) {
    	return 'edit_others_posts';
    }

Хуков нет.

Возвращает

Строку. Название хука, название страницы меню.

Использование

add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );
$page_title(строка) (обязательный)
Текст, который будет использован в теге <title> на странице, относящейся к пункту меню.
$menu_title(строка) (обязательный)
Название пункта меню в сайдбаре админ-панели.
$capability(строка) (обязательный)
Права пользователя (возможности), необходимые чтобы пункт меню появился в списке. Таблицу возможностей смотрите здесь.
$menu_slug(строка) (обязательный)

Уникальное название (slug), по которому затем можно обращаться к этому меню.

Если параметр $function не указан, этот параметр должен равняться названию PHP файла относительно каталога плагинов, который отвечает за вывод кода страницы этого пункта меню.

Можно указать произвольную ссылку (URL), куда будет вести клик пункта меню.

$function(строка)

Название функции, которая выводит контент страницы пункта меню.

Этот необязательный параметр и если он не указан, WordPress ожидает что текущий подключаемый PHP файл генерирует код страницы админ-меню, без вызова функции. Большинство авторов плагинов предпочитают указывать этот параметр.

Два варианта установки параметра:

  1. Если функция является методом класса, она вызывается по ссылке:
    array( $this, 'function_name' )
    или статически:
    array( __CLASS__, 'function_name' ).

  2. Во всех остальных случаях указываем название функции в виде строки.

По умолчанию: ''

$icon_url(строка)

Иконка для пункта меню.

  • Картинка — чтобы подключить произвольную картинку, укажите URL картинки. Для этого можно использовать функцию: plugin_dir_url( __FILE__ ) .'plugin-icon.png'. Размеры картники должны быть 20х20 пикселей или меньше.

  • dashicons — WP использует специальные иконки dashicons, чтобы указать одну из этих иконок, выберите нужную в коллекции иконок и укажите в этом параметре название иконки. Например, иконка консоли называется dashicons-dashboard указываем это название.

  • base64 — можно указывать закодированную в base64 строку, которая будет содержать картинку: data:image/svg+xml;base64,.... В этом случае, иконка будет указана как фон слоя.

    ВАЖНО! С версии WP 6.0 таким образом можно указать только SVG формат (png,jpg работать не будут).

  • none — если указать 'none', то будет создан слой div картинку для которого можно затем указать в CSS стилях.

  • '' — когда указана пустая строка (по умолчанию), используется иконка консоли из списка dashicons и будет добавлен CSS класс menu-icon-generic.
    По умолчанию: ''
$position(число)

Число определяющее позицию меню. Чем больше цифра, тем ниже будет расположен пункт меню.

Внимание! Если два пункта используют одинаковую цифру-позицию, один из пунктов меню может быть перезаписан и будет показан только один пункт из двух. Чтобы избежать конфликта, можно использовать десятичные значения, вместо целых чисел: 63.3 вместо 63. Используйте кавычки: "63.3".

По умолчанию, пункт меню будет добавлен в конец списка.

Список позиций для базовых пунктов меню:

2 Консоль
4 Разделитель
5 Посты
10 Медиа
15 Ссылки
20 Страницы
25 Комментарии
59 Разделитель
60 Внешний вид
65 Плагины
70 Пользователи
75 Инструменты
80 Настройки
99 Разделитель

По умолчанию: null (в конце списка иконок)

Примеры

3

#1 Пункт настройки темы

Этот пример показывает как добавить страницу настроек темы, в главное меню админ-панели WordPress.

<?php
add_action('admin_menu', function(){
	add_menu_page( 'Дополнительные настройки сайта', 'Пульт', 'manage_options', 'site-options', 'add_my_setting', '', 4 );
} );

// функция отвечает за вывод страницы настроек
// подробнее смотрите API Настроек: http://wp-kama.ru/id_3773/api-optsiy-nastroek.html
function add_my_setting(){
	?>
	<div class="wrap">
		<h2><?php echo get_admin_page_title() ?></h2>

		<?php
		// settings_errors() не срабатывает автоматом на страницах отличных от опций
		if( get_current_screen()->parent_base !== 'options-general' )
			settings_errors('название_опции');
		?>

		<form action="options.php" method="POST">
			<?php
				settings_fields("opt_group");     // скрытые защитные поля
				do_settings_sections("opt_page"); // секции с настройками (опциями).
				submit_button();
			?>
		</form>
	</div>
	<?php

}
1

#2 Добавление меню для администратора

Добавим пункт меню в админ-панель, который будет виден только администраторам:

Вариант 1 (только для плагинов):

add_action( 'admin_menu', 'register_my_custom_menu_page' );
function register_my_custom_menu_page(){
	add_menu_page( 'custom menu title', 'custom menu', 'manage_options', 'myplugin/myplugin-admin.php', '', plugins_url( 'myplugin/images/icon.png' ), 6 );
}

В этом случае код страницы должен быть расположен в файле wp-content/plugins/myplugin/myplugin-admin.php:

<?php
	echo "Код страницы.";
?>

Вариант 2:

add_action( 'admin_menu', 'register_my_custom_menu_page' );
function register_my_custom_menu_page(){
	add_menu_page(
		'custom menu title', 'custom menu', 'manage_options', 'custompage', 'my_custom_menu_page', plugins_url( 'myplugin/images/icon.png' ), 6
	);
}

function my_custom_menu_page(){
	echo "Код страницы.";
}
1

#3 Проверка наличия пункта меню или пункта подменю

Эта функция проверяет наличие пункта меню или пункта подменю по указанному идентификатору этого пункта.

/**
 * Находит указанный элемент меню или подменю админки.
 *
 * Нужно использовать после события 'admin_menu'.
 *
 * Пример использования: if( is_admin_menu_item_exists('options-general.php') ){  }
 *
 * @param string $handle Идентификатор пункта меню. Указывается в 4 параметре add_menu_page() или add_submenu_page()
 * @param bool   $sub    Указан ID меню или подменю?
 *
 * @return boolean Есть пункт меню или нет
 */
function is_admin_menu_item_exists( $handle, $sub = false ) {

	if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
		return false;
	}

	global $menu, $submenu;

	$check_menu = $sub ? $submenu : $menu;

	if ( empty( $check_menu ) ) {
		return false;
	}

	foreach ( $check_menu as $k => $item ) {
		if ( $sub ) {
			foreach ( $item as $sm ) {
				if ( $handle == $sm[2] ) {
					return true;
				}
			}
		} 
		elseif ( $handle == $item[2] ) {
			return true;
		}
	}

	return false;
}
1

#4 Пункт меню со ссылкой на редактирование поста

Допустим, нам нужно добавить в меню произвольную ссылку: /wp-admin/post.php?post=270&action=edit:

add_action( 'admin_menu', 'change_menu' );
function change_menu() {
	$post_id  = 393;
	$url_edit = get_edit_post_link( $post_id );

	if ( $url_edit ) {
		add_menu_page( '', 'Моя статья', 'edit_posts', $url_edit, '', '', 5 );
	}
}
0

#5 Добавление пункта меню, с проверкой что его еще нет

Допустим, что перед добавление пункта меню нужно убедится что этот пункт еще не добавлен из другого места. Для того чтобы такую проверку сделать очень быстрой, можно использовать глобальную переменную $admin_page_hooks

global $admin_page_hooks;

if( isset($admin_page_hooks['идентификатор_пункта_меню']) ){
	add_submenu_page( ... );
}
else {
	add_menu_page( ..., ..., ..., 'идентификатор_пункта_меню' );
	add_submenu_page( ... );
}

Заметки

  • Global. Массив. $menu
  • Global. Массив. $admin_page_hooks
  • Global. Массив. $_registered_pages
  • Global. Массив. $_parent_pages

Список изменений

С версии 1.5.0 Введена.

Код add_menu_page() WP 6.7.1

function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) {
	global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;

	$menu_slug = plugin_basename( $menu_slug );

	$admin_page_hooks[ $menu_slug ] = sanitize_title( $menu_title );

	$hookname = get_plugin_page_hookname( $menu_slug, '' );

	if ( ! empty( $callback ) && ! empty( $hookname ) && current_user_can( $capability ) ) {
		add_action( $hookname, $callback );
	}

	if ( empty( $icon_url ) ) {
		$icon_url   = 'dashicons-admin-generic';
		$icon_class = 'menu-icon-generic ';
	} else {
		$icon_url   = set_url_scheme( $icon_url );
		$icon_class = '';
	}

	$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );

	if ( null !== $position && ! is_numeric( $position ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			sprintf(
				/* translators: %s: add_menu_page() */
				__( 'The seventh parameter passed to %s should be numeric representing menu position.' ),
				'<code>add_menu_page()</code>'
			),
			'6.0.0'
		);
		$position = null;
	}

	if ( null === $position || ! is_numeric( $position ) ) {
		$menu[] = $new_menu;
	} elseif ( isset( $menu[ (string) $position ] ) ) {
		$collision_avoider = base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) * 0.00001;
		$position          = (string) ( $position + $collision_avoider );
		$menu[ $position ] = $new_menu;
	} else {
		/*
		 * Cast menu position to a string.
		 *
		 * This allows for floats to be passed as the position. PHP will normally cast a float to an
		 * integer value, this ensures the float retains its mantissa (positive fractional part).
		 *
		 * A string containing an integer value, eg "10", is treated as a numeric index.
		 */
		$position          = (string) $position;
		$menu[ $position ] = $new_menu;
	}

	$_registered_pages[ $hookname ] = true;

	// No parent as top level.
	$_parent_pages[ $menu_slug ] = false;

	return $hookname;
}