这不再是推荐使用主题选项的方式。 Customizer API是为用户提供更多控制和灵活性的推荐方法
主题作者可能需要提供设置屏幕,因此用户可以自定义主题的使用或作品。 执行此操作的最佳方法是创建一个管理菜单项,允许用户从所有管理屏幕访问该设置屏幕。
参考方法
菜单页
- add_menu_page()
- add_object_page()
- add_utility_page()
- remove_menu_page()
子菜单页
- add_submenu_page()
- remove_submenu_page()
WordPress管理菜单
- add_dashboard_page()
- add_posts_page()
- add_media_page()
- add_links_page()
- add_pages_page()
- add_comments_page()
- add_theme_page()
- add_plugins_page()
- add_users_page()
- add_management_page()
- add_options_page()
每个剧情需要一个钩子
要添加管理菜单,您需要做三件事:
- 创建一个包含菜单建立代码的函数。
- 如果要为网络添加菜单,请使用admin_menu操作钩子或network_admin_menu注册上述功能。
- 创建屏幕的HTML输出,当单击菜单项时显示。
大多数开发人员忽略了此列表中的第二步。 你不能简单地调用菜单代码。 你需要把它放在一个函数中,然后注册这个函数。
以下是描述这三个步骤的简单示例。 这将在“设置”顶层菜单下添加一个子级菜单项。 选择时,该菜单项将显示非常基本的屏幕。
<?php
/** Step 2 (from text above). */
add_action( 'admin_menu', 'my_menu' );
/** Step 1. */
function my_menu() {
add_options_page(
'My Options',
'My Menu',
'manage_options',
'my-unique-identifier',
'my_options'
);
}
/** Step 3. */
function my_options() {
if ( !current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
}
echo 'Here is where I output the HTML for my screen.';
echo '</div><pre>';
}
?>
在此示例中,函数my_menu()通过add_options_page()函数将新项添加到设置管理菜单。
注意:请注意,步骤2中的add_action()调用在admin_menu钩子下注册my_menu()函数。 没有这个,add_action()调用,将会抛出一个未定义函数的PHP错误。 最后,add_options_page()调用是指当有人点击菜单项时,包含要显示的实际页面(和要处理的PHP代码)的my_options()函数。
以下部分将对这些步骤进行更详细的描述。 请记住将菜单和页面的创建包含在函数中,并使用admin_menu钩子来在正确的时间开始整个过程。
确定新菜单的位置
在创建新菜单之前,首先决定菜单是顶级菜单还是子级菜单项。顶级菜单显示为管理菜单中的新部分,并包含子级菜单项。这意味着子级菜单项是现有顶级菜单的成员。
主题很少需要创建一个新的顶级菜单。如果这个主题向WordPress引入了一个全新的概念,并且需要许多屏幕来做,那么这个主题可能需要一个新的顶级菜单。只有当您真正需要多个相关屏幕才能使WordPress做最初的设计时,才能考虑添加顶级菜单。新的顶级菜单的示例可能包括作业管理或会议管理。请注意,通过本机帖子类型注册,WordPress会自动创建顶级菜单来管理此类功能。
如果不需要创建顶级菜单,则需要决定在什么顶级菜单中放置新的子级菜单项。作为参考,几个主题添加了现有WordPress顶层菜单下的子级菜单项。
使用本指南的WordPress顶级菜单来确定您的子级菜单项的正确位置:
- Dashboard – 信息中心为您的网站,并包括更新选项更新WordPress核心,插件和主题。
- Posts – 显示用于撰写帖子(面向时间的内容)的工具。
- Media – 上传和管理您的图片,视频和音频。
- Links – 管理对其他博客和感兴趣的网站的引用。
- Pages – 显示用于编写称为页面的静态内容的工具。
- Comments – 控制和监管读者对帖子的回复。
- Appearance – 显示用于操纵theme/style文件,侧边栏等的控件。
- Plugins – 显示处理插件管理的控件,而不是插件本身的配置选项。
- Users – 显示用户管理控件。
- Tools – 管理博客数据的导出,导入甚至备份。
- Settings – 显示只有管理员应该查看的插件选项。
- Network Admin – 显示在网络上设置的插件选项。 而不是admin_menu,您应该使用network_admin_menu(另请参阅创建网络)
顶级菜单
如果您决定了您的主题需要一个全新的顶级菜单,您需要做的第一件事是使用add_menu_page()函数创建一个。
注意:如果您不需要顶级菜单,请跳到“子级菜单”。
参数值:
- page_title – 选择菜单时要显示在页面的标题标签中的文本。
- menu_title – 菜单的屏幕上的名称文本。
- capability – 该菜单显示给用户所需的功能。 当使用Settings API处理表单时,您应该在此处使用manage_options,因为用户将无法保存其中的选项。 用户级别已弃用,不能在此处使用。
- menu_slug – 这个菜单由这个菜单引用(这个菜单应该是唯一的)。 在版本3.0之前,这被称为文件(或句柄)参数。 如果功能参数被省略,则menu_slug应该是处理菜单页面内容显示的PHP文件。
- function – 显示菜单页面的页面内容的功能。
- icon_url – 要用于此菜单的图标的URL。 此参数是可选的。
- position – 菜单中的位置这个菜单应该出现。 默认情况下,如果省略此参数,菜单将显示在菜单结构的底部。 要查看当前的菜单位置,请在菜单加载后使用print_r($ GLOBALS ['menu'])。
- Sub-Level Menus – 一旦定义了顶级菜单,或者您选择使用现有的WordPress顶级菜单,就可以使用add_submenu_page()函数定义一个或多个子级菜单项。
子菜单
如果您想要将新菜单项设为子菜单项,可以使用add_submenu_page()函数创建它。
参数值:
parent_slug - 父菜单的小数名称,或标准WordPress管理员文件的文件名,提供要插入子菜单的顶级菜单,或者如果此子菜单正在进行,则为插件文件 自定义顶级菜单。 例子:
- Dashboard – add_submenu_page('index.php', ...)
- Posts – add_submenu_page('edit.php', ...)
- Media – add_submenu_page('upload.php', ...)
- Links – add_submenu_page('link-manager.php', ...)
- Pages – add_submenu_page('edit.php?post_type=page', ...)
- Comments – add_submenu_page('edit-comments.php', ...)
- Custom Post Types – add_submenu_page('edit.php?post_type=your_post_type', ...)
- Appearance – add_submenu_page('themes.php', ...)
- Plugins – add_submenu_page('plugins.php', ...)
- Users – add_submenu_page('users.php', ...)
- Tools – add_submenu_page('tools.php', ...)
- Settings – add_submenu_page('options-general.php', ...)
- page_title – 当子菜单处于活动状态时,将进入页面的HTML页面标题的文本。
- menu_title – 选择菜单时要显示在页面的标题标签中的文本。
- capability – 该菜单显示给用户所需的功能。 用户级别已弃用,不能在此处使用。
- menu_slug – 对于现有的WordPress菜单,处理菜单页面内容显示的PHP文件。 对于自定义顶级菜单的子菜单,此子菜单页面的唯一标识符。
- function – 显示菜单页面的页面内容的功能。 在技术上,如在add_menu_page函数中,函数参数是可选的,但是如果没有提供,那么WordPress基本上会假设包含PHP文件将生成管理屏幕,而不调用函数。
使用包装器功能
由于大多数子级菜单属于“设置”,“工具”或“外观”菜单,所以WordPress提供了包装功能,可以使这些顶级菜单中的子级菜单项更容易。 请注意,功能名称可能与管理UI中看到的名称不一致,因为它们随时间变化:
- Dashboard
<?php add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Posts
<?php add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Media
<?php add_media_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Links
<?php add_links_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Pages
<?php add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Comments
<?php add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Appearance
<?php add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Plugins
<?php add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Users
<?php add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Tools
<?php add_management_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
- Settings
<?php add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function); ?>
另请参阅主题选项,用于通过Customizer API创建选项的当前推荐方法。
示例
以下是一个快速示例,说明如何插入顶层菜单页和子菜单页,子菜单页上的标题与顶级页不同。 在此示例中,register_my_theme_more_settings_menu是显示第一个子菜单页面的函数的名称:
function register_my_theme_settings_menu() {
add_menu_page(
"My Theme's Settings",
"My Theme",
"manage_options",
"my-theme-settings-menu"
);
}
function register_my_theme_more_settings_menu() {
add_submenu_page(
"my-themes-settings-menu",
"More Settings for My Theme",
"More Settings",
"manage_options",
"my-theme-more-settings-menu"
);
}
add_action( "admin_menu", "register_my_theme_settings_menu");
add_action( "admin_menu", "register_my_theme_more_settings_menu");
以下是在自定义帖子类型菜单块下添加选项页面的示例(另见此处):
插入页面
以下是一个如何将多个菜单插入到各个地方的示例:
<?php
// Hook for adding admin menus
add_action('admin_menu', 'mt_add_pages');
// Action function for hook above
function mt_add_pages() {
// Add a new submenu under Settings:
add_options_page(__('Test Settings','menu-test'), __('Test Settings','menu-test'), 'manage_options', 'testsettings', 'mt_settings_page');
// Add a new submenu under Tools:
add_management_page( __('Test Tools','menu-test'), __('Test Tools','menu-test'), 'manage_options', 'testtools', 'mt_tools_page');
// Add a new top-level menu (ill-advised):
add_menu_page(__('Test Toplevel','menu-test'), __('Test Top-level','menu-test'), 'manage_options', 'mt-top-level-handle', 'mt_toplevel_page' );
// Add a submenu to the custom top-level menu:
add_submenu_page('mt-top-level-handle', __('Test Sub-Level','menu-test'), __('Test Sub-Level','menu-test'), 'manage_options', 'sub-page', 'mt_sublevel_page');
// Add a second submenu to the custom top-level menu:
add_submenu_page('mt-top-level-handle', __('Test Sub-Level 2','menu-test'), __('Test Sub-Level 2','menu-test'), 'manage_options', 'sub-page2', 'mt_sublevel_page2');
}
// mt_settings_page() displays the page content for the Test settings sub-menu
function mt_settings_page() {
echo "</pre>
<h2>" . __( 'Test Settings', 'menu-test' ) . "</h2>
<pre>
";
}
// mt_tools_page() displays the page content for the Test Tools sub-menu
function mt_tools_page() {
echo "</pre>
<h2>" . __( 'Test Tools', 'menu-test' ) . "</h2>
<pre>
";
}
// mt_toplevel_page() displays the page content for the custom Test Top-Level menu
function mt_toplevel_page() {
echo "</pre>
<h2>" . __( 'Test Top-Level', 'menu-test' ) . "</h2>
<pre>
";
}
// mt_sublevel_page() displays the page content for the first sub-menu
// of the custom Test Toplevel menu
function mt_sublevel_page() {
echo "</pre>
<h2>" . __( 'Test Sub-Level', 'menu-test' ) . "</h2>
<pre>
";
}
// mt_sublevel_page2() displays the page content for the second sub-menu
// of the custom Test Top-Level menu
function mt_sublevel_page2() {
echo "</pre>
<h2>" . __( 'Test Sub-Level 2', 'menu-test' ) . "</h2>
<pre>
";
}
?>
样品菜单页
注意:有关创建设置页面的信息,请参阅设置API。
前面的示例包含几个虚拟函数,如mt_settings_page()作为实际页面内容的占位符。 我们来扩大他们。 如果您想创建一个名为mt_favorite_color的选项,如果网站所有者可以通过“设置”页面输入最喜欢的颜色,该怎么办? mt_options_page()函数需要在屏幕上输出数据输入表单,并处理输入的数据。
这是一个这样做的功能:
// mt_settings_page() displays the page content for the Test settings sub-menu
function mt_settings_page() {
//must check that the user has the required capability
if (!current_user_can('manage_options'))
{
wp_die( __('You do not have sufficient permissions to access this page.') );
}
// Variables for the field and option names
$opt_name = 'mt_favorite_color';
$hidden_field_name = 'mt_submit_hidden';
$data_field_name = 'mt_favorite_color';
// Read in existing option value from database
$opt_val = get_option( $opt_name );
// See if the user has posted us some information
// If they did, this hidden field will be set to 'Y'
if( isset($_POST[ $hidden_field_name ]) && $_POST[ $hidden_field_name ] == 'Y' ) {
// Read their posted value
$opt_val = $_POST[ $data_field_name ];
// Save the posted value in the database
update_option( $opt_name, $opt_val );
// Put a "Settings updated" message on the screen
?>
<div class="updated"></div>
<div class="wrap">
<?php
// Header
echo "<h2>" . __( 'Menu Test Settings', 'menu-test' ) . "</h2>";
// Settings form
?>
<form action="" method="post" name="form1"></form>
<?php _e("Favorite Color:", 'menu-test' ); ?>
<hr />
</div>
<?php } ?>
几个注释:
- WordPress函数(如add_menu_page()和add_submenu_page())具有一个功能,用于确定是否显示顶级或子级菜单。
- 挂接以处理页面输出的功能必须检查用户是否具有所需的功能。
- WordPress管理功能负责验证用户登录,因此您不必担心您的功能。
- 上述功能示例已被国际化 - 有关详细信息,请参阅I18n for WordPress开发人员。
- 在将数据输入表单放在屏幕上之前,该函数将处理任何输入的数据,以便新值将以表单(而不是数据库的值)显示。
- 您不必担心这是第一次工作,因为WordPress update_option函数会自动向数据库添加一个选项,如果它不存在。
- 这些管理菜单添加过程将在您每次导航到管理员中的页面时进行解析。因此,如果您正在撰写一个没有选项页面的主题,但稍后添加一个主题,您可以使用上面的说明添加它,并重新上传,并调整,直到您满意为止。换句话说,菜单在激活主题时不会“永久添加”或放入数据库。他们在飞行中解析,所以您可以随意添加或减少菜单项,重新上传,更改将立即反映。
页钩子后缀
添加新管理菜单的每个功能 - add_menu_page(),add_submenu_page()及其专门版本(如add_options_page())返回一个名为“页面钩子后缀”的特殊值。 它可以稍后用作挂钩,只能在该特定页面上调用一个动作。
一个这样的动作钩子是load-{page_hook},其中{page_hook}是这些add _ * _ page()函数之一返回的值。 当加载特定页面时调用此钩子。 在下面的示例中,它用于在所有管理页面上显示“主题未配置”通知,但插件的选项页面除外:
<?php
add_action('admin_menu', 'my_menu');
// Here you can check if plugin is configured (e.g. check if some option is set). If not, add new hook.
// In this example hook is always added.
add_action( 'admin_notices', 'my_admin_notices' );
function my_menu() {
// Add the new admin menu and page and save the returned hook suffix
$hook_suffix = add_options_page('My Options', 'My Theme', 'manage_options', 'my-unique-identifier', 'my_options');
// Use the hook suffix to compose the hook and register an action executed when plugin's options page is loaded
add_action( 'load-' . $hook_suffix , 'my_load_function' );
}
function my_load_function() {
// Current admin page is the options page for our plugin, so do not display the notice
// (remove the action responsible for this)
remove_action( 'admin_notices', 'my_admin_notices' );
}
function my_admin_notices() {
echo '<pre>
<div class="updated fade" id="notice">
My Plugin is not configured yet. Please do it now.</div>
</pre>';
}
function my_options() {
if (!current_user_can('manage_options')) {
wp_die( __('You do not have sufficient permissions to access this page.') );
}
echo '</pre>
<div class="wrap">';
echo 'Here is where the form would go if I actually had options.';
echo '</div>
<pre>
';
}
?>
资源
关于wp-hackers的顶级菜单讨论
管理员菜单编辑器插件