WordPress как на ладони
Очень Удобный и Быстрый Хостинг для сайтов на WordPress. Пользуюсь сам и вам рекомендую!

add_submenu_page()WP 1.5.0

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

Указав минимальные права пользователя, можно ограничить доступ к меню.

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

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

Функция (параметр $function), которая отвечает за вывод контента на странице должна проверять права пользователя отдельно и если нужно блокировать доступ к контенту.

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

Не используйте __FILE__ для параметра $menu_slug. Так вы получите нерабочий URL и дыру в защите.

При написании кода функции указанной в параметре $function, вам возможно нужны будут параметры указанные для add_submenu_page(), например $page_title. Получить их можно так:

  • $parent_slug - get_admin_page_parent();
  • $page_title - get_admin_page_title() или просто используйте глобальную переменную $title;
  • $menu_slug - глобальная переменная $plugin_page

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

Читайте также: API настроек (опций)

Основа для: add_options_page(), add_theme_page()

Хуков нет.

Возвращает

Строку|false. Название хука, результирующей страницы меню или false, если пользователь не имеет прав доступа к меню.

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

add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function, $position );
$parent_slug(строка) (обязательный)

Название (slug) родительского меню в которое будет добавлен пункт или название файла админ-страницы WordPress.

Используйте пустую строку options.php, чтобы создать страницу, которая не будет появляться в пункте меню админки. Работает и для мультисайта.

Примеры:

  • options.php - скрытая страница.
  • index.php - Консоль (Dashboard). Или функция add_dashboard_page();
  • edit.php - Посты (Posts). Или функция add_posts_page();
  • upload.php - Медиафайлы (Media). Или функция add_media_page();
  • link-manager.php - Ссылки (Links). Или функция add_links_page();
  • edit.php?post_type=page - Страницы (Pages). Или функция add_pages_page();
  • edit-comments.php - Комментарии (Comments). Или функция add_comments_page();
  • edit.php?post_type=your_post_type - Произвольные типы записей.
  • themes.php - Внешний вид (Appearance). Или функция add_theme_page();
  • plugins.php - Плагины (Plugins). Или функция add_plugins_page();
  • users.php - Пользователи (Users). Или функция add_users_page();
  • tools.php - Инструменты (Tools). Или функция add_management_page();
  • options-general.php - Настройки (Settings). Или функция: add_options_page()
  • settings.php - Настройки (Settings) сети сайтов в MU режиме.
$page_title(строка) (обязательный)
Текст, который будет использован в теге title на странице.
$menu_title(строка) (обязательный)
Текст, который будет использован как название пункта меню.
$capability(строка) (обязательный)
Возможность пользователя, чтобы иметь доступ к меню. Таблицу возможностей смотрите здесь. Этот параметр отвечает и за доступ к странице этого пункта меню.
$menu_slug(строка) (обязательный)

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

Это название будет использоваться в качестве значение параметра запроса page в ссылке на страницу: ?page=название. Это уникальное название будет как бы привязано к функции указанной в следующем параметре $function.

По неофициальной информации, в этот параметр можно добавить путь до файла отвечающего за страницу этого пункта меню. Путь должен быть от каталога плагинов: допустим папка плагина называетсяmy-plugin и файл страницы настроек options.php, тогда путь до файла будет такой: my-plugin/options.php.

$function(строка/массив)

Название функции которая будет вызваться, чтобы вывести контент создаваемой страницы.
Два варианта установки параметра:

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

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

$position(число)
Позиция подпункта меню, относительно других подпунктов. Добавлено в WP 5.3.0.
По умолчанию: null

Примеры

1

#1 Подменю для произвольно-созданного меню

Если вы пытаетесь добавить пункт меню в основной раздел, который вы создали самостоятельно с помощью add_menu_page(), то первый пункт будет копией созданного пункта add_menu_page(). Это видно во всем меню WordPress.

Если вам нужен пункт подменю по такому сценарию, то для начала вам нужно создать дубль основного меню, а затем добавить подменю:

add_menu_page( 'Основное доп. меню', 'Мое основное меню', 'manage_options', 'my-top-level-slug' );

add_submenu_page( 'my-top-level-slug', 'Основное доп. меню', 'Мое основное меню', 'manage_options', 'my-top-level-slug');

add_submenu_page( 'my-top-level-slug', 'Мое подменю', 'Страница настроек моего подменю', 'manage_options', 'my-secondary-slug', 'page_callback_function');
1

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

Смотрите в примерах add_menu_page()

0

#3 Добавим подменю в меню админ-панели "Инструменты" (tools):

// Добавим подменю в меню админ-панели "Инструменты" (tools):
add_action('admin_menu', 'register_my_custom_submenu_page');

function register_my_custom_submenu_page() {
	add_submenu_page(
		'tools.php',
		'Дополнительная страница инструментов',
		'Название инструмента',
		'manage_options',
		'my-custom-submenu-page',
		'my_custom_submenu_page_callback'
	);
}

// контент страницы
function my_custom_submenu_page_callback() {
	?>
	<div class="wrap">
		<h2><?= get_admin_page_title() ?></h2>
	</div>
	<?php
}
0

#4 Прячем страницу из меню, но она все равно будет рабочей

Чтобы спрятать ссылку пункта подменю из основного меню админ-панели, используйте первый параметр null или 'options.php':

// Прячем страницу из меню, но она все равно будет рабочей
add_action( 'admin_menu', 'register_my_custom_submenu_page' );

function register_my_custom_submenu_page() {
	add_submenu_page(
		'options.php',
		'Произвольная страница подменю',
		'Произвольная страница подменю',
		'manage_options',
		'my-custom-submenu-page',
		'my_custom_submenu_page_callback'
	);
}
0

#5 Без указания функции страницы настроек (неофициально)

В официальной документации этого нет. В параметре $menu_slug можно указать путь до страницы опций, от каталога плагинов. В этом случае не нужно указывать функцию отвечающую за код страницы настроек. Для страницы настроек у нас будет отдельный файл. Предположим наш файл страницы настроек лежит в корне папки плагина и называется options.php, тогда страница настроек плагина регистрируется так:

add_action( 'admin_menu', 'add_options_page' );

function add_options_page(){

	add_submenu_page( 
		'options-general.php', 
		'Заголовок страницы', 
		'Название пункта меню', 
		'manage_options', 
		basename( dirname(__FILE__) ) . '/options.php' 
	);
}

Тут basename(dirname(__FILE__)).'/options.php' равно название_папки_плагина/options.php.

0

#6 Использование возвращаемого хука

Функция возвращает суффикс хука страницы, который можно использовать в хуке load-page_hook:

$hookname = add_submenu_page( 
	'options-general.php', 
	$page_title, 
	$menu_title, 
	$capability, 
	$menu_slug, 
	$callback, 
	$position 
);

add_action( "load-{$hookname}", 'my_admin_load' );

function my_admin_load(){
	// do staff
}

Заметки

  • Global. Массив. $submenu
  • Global. Массив. $menu
  • Global. Массив. $_wp_real_parent_file
  • Global. true|false. $_wp_submenu_nopriv
  • Global. Массив. $_registered_pages
  • Global. Массив. $_parent_pages

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

С версии 1.5.0 Введена.
С версии 5.3.0 Added the $position parameter.

Код add_submenu_page() WP 6.5.2

function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv,
		$_registered_pages, $_parent_pages;

	$menu_slug   = plugin_basename( $menu_slug );
	$parent_slug = plugin_basename( $parent_slug );

	if ( isset( $_wp_real_parent_file[ $parent_slug ] ) ) {
		$parent_slug = $_wp_real_parent_file[ $parent_slug ];
	}

	if ( ! current_user_can( $capability ) ) {
		$_wp_submenu_nopriv[ $parent_slug ][ $menu_slug ] = true;
		return false;
	}

	/*
	 * If the parent doesn't already have a submenu, add a link to the parent
	 * as the first item in the submenu. If the submenu file is the same as the
	 * parent file someone is trying to link back to the parent manually. In
	 * this case, don't automatically add a link back to avoid duplication.
	 */
	if ( ! isset( $submenu[ $parent_slug ] ) && $menu_slug !== $parent_slug ) {
		foreach ( (array) $menu as $parent_menu ) {
			if ( $parent_menu[2] === $parent_slug && current_user_can( $parent_menu[1] ) ) {
				$submenu[ $parent_slug ][] = array_slice( $parent_menu, 0, 4 );
			}
		}
	}

	$new_sub_menu = array( $menu_title, $capability, $menu_slug, $page_title );

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

	if (
		null === $position ||
		( ! isset( $submenu[ $parent_slug ] ) || $position >= count( $submenu[ $parent_slug ] ) )
	) {
		$submenu[ $parent_slug ][] = $new_sub_menu;
	} else {
		// Test for a negative position.
		$position = max( $position, 0 );
		if ( 0 === $position ) {
			// For negative or `0` positions, prepend the submenu.
			array_unshift( $submenu[ $parent_slug ], $new_sub_menu );
		} else {
			$position = absint( $position );
			// Grab all of the items before the insertion point.
			$before_items = array_slice( $submenu[ $parent_slug ], 0, $position, true );
			// Grab all of the items after the insertion point.
			$after_items = array_slice( $submenu[ $parent_slug ], $position, null, true );
			// Add the new item.
			$before_items[] = $new_sub_menu;
			// Merge the items.
			$submenu[ $parent_slug ] = array_merge( $before_items, $after_items );
		}
	}

	// Sort the parent array.
	ksort( $submenu[ $parent_slug ] );

	$hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
	if ( ! empty( $callback ) && ! empty( $hookname ) ) {
		add_action( $hookname, $callback );
	}

	$_registered_pages[ $hookname ] = true;

	/*
	 * Backward-compatibility for plugins using add_management_page().
	 * See wp-admin/admin.php for redirect from edit.php to tools.php.
	 */
	if ( 'tools.php' === $parent_slug ) {
		$_registered_pages[ get_plugin_page_hookname( $menu_slug, 'edit.php' ) ] = true;
	}

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

	return $hookname;
}
5 комментариев
    Войти