当前浏览:首页 / WordPress函数 / add_menu_page()

add_menu_page( string $page_title, string $menu_title, string $capability, string $menu_slug, callable $callback = '', string $icon_url = '', int|float $position = null )

添加顶级菜单页

addmore...

menu_page 菜单页more...


描述

这个函数接受一个能力(capability),它将被用来确定一个页面是否包括在菜单中。

用于处理页面输出的函数必须检查用户是否具有所需的能力。


参数

$page_title

(string)(必填) 选中菜单时要在页面标题标签中显示的文本。

$menu_title

(string)(必填) 要用于菜单的文本。

$capability

(string)(必填) 向用户显示此菜单所需的能力权限。

$menu_slug

(string)(必填) 用于引用此菜单的slug名称。此菜单页应是唯一的,并且仅包括小写字母数字、破折号和下划线字符,以与sanitize_key()兼容。

$callback

(callable)(可选) 要调用以输出此页面内容的函数。

默认值: ''

$icon_url

(string)(可选) 用于此菜单的图标的URL。

  • 使用数据URI传递base64编码的SVG,该URI将被着色以匹配颜色方案。应该以“data:image/svg+xml;base64,”开始。
  • 传递Dashicons助手类的名称以使用字体图标,例如'dashicons-chart-pie'。
  • 传递'none'将div.wp-menu-image留空,以便通过CSS添加图标。

默认值: ''

$position

(int|float)(可选) 此项应出现在菜单顺序中的位置。

默认值: null


返回

(string) 结果页的hook_suffix。


更多信息

注意

  • 重要提示:自WordPress 4.4,您无需担心位置编号是否唯一以避免冲突。有关更多信息,请参阅trac ticket #23316

 

  • 如果您遇到了“您没有足够的权限访问此页面”错误,则说明您挂钩太早了。您应该使用的挂钩是admin_menu
  • 如果只想将现有的管理菜单项移动到不同的位置,可以使用admin_menu钩子从全局$menu$submenu变量(即数组)中的当前位置取消设置菜单项,并在数组中的其他位置重置它们。
  • 这个函数需要一个“能力”(请参见角色和能力),它将被用来决定一个页面是否被包括在菜单中。用于处理页面输出的函数必须检查用户是否具有所需的“能力”。
  • 如果您使用设置API,并且需要用户不是管理员,则需要通过挂钩option_page_capability_{$option_group}修改权限,其中$option_groupregister_setting()中的option_group相同。查看设置API

允许编辑器保存数据的示例:

// Register settings using the Settings API 
function wpdocs_register_my_setting() {
	register_setting( 'my-options-group', 'my-option-name', 'intval' ); 
} 
add_action( 'admin_init', 'wpdocs_register_my_setting' );

// Modify capability
function wpdocs_my_page_capability( $capability ) {
	return 'edit_others_posts';
}
add_filter( 'option_page_capability_my-options-group', 'wpdocs_my_page_capability' );

默认:菜单结构的底部

  • 2 – Dashboard(仪表盘)
  • 4 – Separator(分隔)
  • 5 – Posts(文章)
  • 10 – Media(媒体)
  • 15 – Links(链接)
  • 20 – Pages(页面)
  • 25 – Comments(评论)
  • 59 – Separator(分隔)
  • 60 – Appearance(外观)
  • 65 – Plugins(插件)
  • 70 – Users(用户)
  • 75 – Tools(工具)
  • 80 – Settings(设置)
  • 99 – Separator(分隔)

对于“网络管理”菜单,值有所不同:

  • 2 – Dashboard(仪表盘)
  • 4 – Separator(分隔)
  • 5 – Sites(站点)
  • 10 – Users(用户)
  • 15 – Themes(主题)
  • 20 – Plugins(插件)
  • 25 – Settings(设置)
  • 30 – Updates(更新)
  • 99 – Separator(分隔)


源码

查看源码 官方文档


更新日志

版本描述
1.5.0开始引入

使用示例

  • 示例1

    示例
    为具有管理员能力的用户在WordPress管理菜单中添加自定义菜单项:

    方法1:

    /**
     * Register a custom menu page.
     */
    function wpdocs_register_my_custom_menu_page() {
    	add_menu_page(
    		__( 'Custom Menu Title', 'textdomain' ),
    		'custom menu',
    		'manage_options',
    		'myplugin/myplugin-admin.php',
    		'',
    		plugins_url( 'myplugin/images/icon.png' ),
    		6
    	);
    }
    add_action( 'admin_menu', 'wpdocs_register_my_custom_menu_page' );
    

    使用此方法,页面生成代码应位于myplugin/myplugin-admin.php

    <?php esc_html_e( 'Admin Page Test', 'textdomain' ); ?>
    

    方法2:

    /**
     * Register a custom menu page.
     */
    function wpdocs_register_my_custom_menu_page(){
    	add_menu_page( 
    		__( 'Custom Menu Title', 'textdomain' ),
    		'custom menu',
    		'manage_options',
    		'custompage',
    		'my_custom_menu_page',
    		plugins_url( 'myplugin/images/icon.png' ),
    		6
    	); 
    }
    add_action( 'admin_menu', 'wpdocs_register_my_custom_menu_page' );
    
    /**
     * Display a custom menu page
     */
    function my_custom_menu_page(){
    	esc_html_e( 'Admin Page Test', 'textdomain' );	
    }
    
  • 示例2

    如果使用数据URI传递base64编码的SVG,则只有在具有fill样式属性的情况下,才会将其着色以匹配配色方案。该过程由wp-admin/js/svg-painter.js完成。

  • 示例3

    要添加解析为子菜单项的顶级菜单项,每个add_menu_page和add_submenu_page调用的菜单slug需要匹配。当您需要顶级菜单项标签与第一个子级菜单项不同时,此选项非常有用。否则,顶级项标签将作为第一个子项重复。

    最小示例-

    $menu_slug = 'wpdocs-orders-slug';
    add_menu_page( 'WP Docs Orders', 'WP Docs Orders', 'read', $menu_slug, false );
    add_submenu_page( $menu_slug, 'Existing WP Docs Orders', 'Existing WP Docs Orders', 'read', $menu_slug, 'wpdocs_orders_function' );

    在该示例中,选择“WP Docs Orders”顶级项目时,将触发子菜单项目。

  • 示例4

    添加带有Dashicons图标的菜单页面。更多dashicons请点击此处https://developer.wordpress.org/resource/dashicons/#menu

    add_action( 'admin_menu', 'register_my_custom_menu_page' );
    function register_my_custom_menu_page() {
      // add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );
      add_menu_page( 'Custom Menu Page Title', 'Custom Menu Page', 'manage_options', 'custom.php', '', 'dashicons-welcome-widgets-menus', 90 );
    }
    
  • 示例5
    /**
     * Create admin Page to list unsubscribed emails.
     */
     // Hook for adding admin menus
     add_action('admin_menu', 'wpdocs_unsub_add_pages');
    
     // action function for above hook
    
    /**
     * Adds a new top-level page to the administration menu.
     */
    function wpdocs_unsub_add_pages() {
         add_menu_page(
    	 	__( 'Unsub List', 'textdomain' ),
    		__( 'Unsub Emails','textdomain' ),
    		'manage_options',
    		'wpdocs-unsub-email-list',
    		'wpdocs_unsub_page_callback',
    		''
    	);
    }
    
    /**
     * Disply callback for the Unsub page.
     */
     function wpdocs_unsub_page_callback() {
         echo 'Unsubscribe Email List';
     }
     
  • 示例6

    添加自定义SVG图标。

    我对此有些费劲,想在使用$icon_url参数时添加一些注释。根据我的经验和在论坛上的观察,使用自定义图标并不像创建SVG并对其进行编码那样简单。以下是将自定义SVG图标添加到管理菜单的分步过程:

    1. 首先,以任何方式获取或创建SVG图标。
    2. 接下来,清理SVG文件并正确格式化
    3. 然后对文件进行base64编码
    4. 在base64字符串前面加上'data:image/svg+xml;base64,'
    5. …这将为您提供一个有效的$icon_url字符串。

    因此,让我详细介绍一下这些步骤。

    步骤1

    据我所知,您可以以任何方式创建SVG图形。我在Adobe Illustrator中创建了我的,但任何像Inkscape、Corel draw,甚至硬编码都可以。

    步骤2

    最痛苦的部分是清理SVG。经过大量测试和实验,我发现SVG越干净,工作的可能性就越大。基本上,许多图形程序将添加元数据和其他杂项,以使SVG更广泛地兼容。这在99%的情况下都很好,但当将其用于wordpress菜单图标时,它只是破坏了它。

    这是一个通常从Adobe Illustrator导出的SVG示例:

    <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 
    15.7 16"><defs><style>.d{fill:#070707;}</style></defs><g id="a"/><g id="b"><g id="c"><path
     class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5
    ,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,
    7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/><path class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,
    3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.
    4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/></g>
    </g></svg>
    

    凌乱,非常凌乱。即使我们添加一些换行符和缩进,也会发生很多事情。

    <?xml version="1.0" encoding="UTF-8"?>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.7 16">
    	<defs>
    		<style>
    			.d{fill:#070707;}
    		</style>
    	</defs>
    	<g id="a"/>
    	<g id="b">
    		<g id="c">
    			<path class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/>
    			<path class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/>
    		</g>
    	</g>
    </svg>
    

    所以我们要做的是大量清理这些数据,并去除不必要的数据。如果将其添加为图像源,您可能会发现上面的内容将被加载,但它无法使用GUI正确着色,并且可能大小错误。因此,我们需要做几件事:

    • 删除<?xml标记,这不会有帮助
    • 然后,您必须将每个样式硬编码到路径中,而不是使用标记。对于每个路径,从标记中找出哪些类应用于路径,并将这些类中的CSS添加到路径中。
    • 完成后,可以完全删除defs元素。
    • 您还可以删除元素并将元素保留在SVG的根目录下。
    • 为了确保SVG的颜色与GUI一致,需要向每个路径添加fill="black"
    • 然后,为了确保SVG的宽度和高度正确,将width="20" height="20"添加到open元素中

    完成后,您将得到一个SVG文件,看起来更像这样:

    <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
    	<path fill="black" d="M17.6 8.5h-7.5v3h4.4c-.4 2.1-2.3 3.5-4.4 3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7 2-5 4.7-5.1 1.1 0 2.2.4 3.1 1.2l2.3-2.2C14.1 2.7 12.1 2 10.2 2c-4.4 0-8 3.6-8 8s3.6 8 8 8c4.6 0 7.7-3.2 7.7-7.8-.1-.6-.1-1.1-.3-1.7z" fillrule="evenodd" cliprule="evenodd">
    	</path>
    </svg>
    

    步骤3

    现在您需要对SVG进行base64编码。我这样做的方式是将文件传递到PHP的默认编码机制中,并将路径作为绝对路径复制到我的PHP中。您不希望PHP读取SVG文件,对其进行base64编码,并在用户每次重新加载页面时将其传递到菜单,这只是浪费资源和时间。

    // load the SVG data by loading the file or including the XML directly.
    $svg = file_get_contents( '/path/to/icon.svg' );
    // or
    $svg = '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill="black" d="M17.6 8.5h-7.5v3h4.4c-.4 2.1-2.3 3.5-4.4 3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7 2-5 4.7-5.1 1.1 0 2.2.4 3.1 1.2l2.3-2.2C14.1 2.7 12.1 2 10.2 2c-4.4 0-8 3.6-8 8s3.6 8 8 8c4.6 0 7.7-3.2 7.7-7.8-.1-.6-.1-1.1-.3-1.7z" fillrule="evenodd" cliprule="evenodd"></path></svg>';
    
    // then encode it and echo it out
    echo base64_encode( $svg );
    // will give you a long string that looks like this:
    // PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdib3g9IjAgMCAyMCAyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjYTdhYWFkIiBkPSJNMTcuNiA4LjVoLTcuNXYzaDQuNGMtLjQgMi4xLTIuMyAzLjUtNC40IDMuNC0yLjYtLjEtNC42LTIuMS00LjctNC43LS4xLTIuNyAyLTUgNC43LTUuMSAxLjEgMCAyLjIuNCAzLjEgMS4ybDIuMy0yLjJDMTQuMSAyLjcgMTIuMSAyIDEwLjIgMmMtNC40IDAtOCAzLjYtOCA4czMuNiA4IDggOGM0LjYgMCA3LjctMy4yIDcuNy03LjgtLjEtLjYtLjEtMS4xLS4zLTEuN3oiIGZpbGxydWxlPSJldmVub2RkIiBjbGlwcnVsZT0iZXZlbm9kZCI+PC9wYXRoPjwvc3ZnPg==
    
    // thats your base64 encoded SVG file! 
    

    步骤4

    在base64 SVG前面添加‘data:image/svg+xml;’,如下所示:

    "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdib3g9IjAgMCAyMCAyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjYTdhYWFkIiBkPSJNMTcuNiA4LjVoLTcuNXYzaDQuNGMtLjQgMi4xLTIuMyAzLjUtNC40IDMuNC0yLjYtLjEtNC42LTIuMS00LjctNC43LS4xLTIuNyAyLTUgNC43LTUuMSAxLjEgMCAyLjIuNCAzLjEgMS4ybDIuMy0yLjJDMTQuMSAyLjcgMTIuMSAyIDEwLjIgMmMtNC40IDAtOCAzLjYtOCA4czMuNiA4IDggOGM0LjYgMCA3LjctMy4yIDcuNy03LjgtLjEtLjYtLjEtMS4xLS4zLTEuN3oiIGZpbGxydWxlPSJldmVub2RkIiBjbGlwcnVsZT0iZXZlbm9kZCI+PC9wYXRoPjwvc3ZnPg=="
    

    这是一个完全有效的$icon_url字符串。我会把这个字符串硬编码成一个变量,然后每次都把它添加到你的插件中。

    add_menu_page( __( 'WPDocs Plugin page name' ), __( 'WPDocs Plugin' ), 'manage_options', 'slug', 'callback','data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdib3g9IjAgMCAyMCAyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjYTdhYWFkIiBkPSJNMTcuNiA4LjVoLTcuNXYzaDQuNGMtLjQgMi4xLTIuMyAzLjUtNC40IDMuNC0yLjYtLjEtNC42LTIuMS00LjctNC43LS4xLTIuNyAyLTUgNC43LTUuMSAxLjEgMCAyLjIuNCAzLjEgMS4ybDIuMy0yLjJDMTQuMSAyLjcgMTIuMSAyIDEwLjIgMmMtNC40IDAtOCAzLjYtOCA4czMuNiA4IDggOGM0LjYgMCA3LjctMy4yIDcuNy03LjgtLjEtLjYtLjEtMS4xLS4zLTEuN3oiIGZpbGxydWxlPSJldmVub2RkIiBjbGlwcnVsZT0iZXZlbm9kZCI+PC9wYXRoPjwvc3ZnPg==' );
    

    我希望这对其他人有帮助,因为这会让我今天早上节省几个小时!

  • 示例7

    这是一个更好的例子,peskyesky

    这是一个面向对象的例子。

    待办事项:
    创建includes/layout.php

    class WPDocs_EB_EbtechModules {
        public static function init() {
            add_action( 'admin_enqueue_scripts', array( __CLASS__, 'adminAssets' ) );
            add_action( 'admin_menu', array( __CLASS__, 'adminMenu' ) );
        }
    
        public static function adminMenu() {
            add_menu_page(
                __( 'WPDocs Ebtech Menu', 'wpdocs-webnail-modules' ),
                __( 'WPDocs Ebtech modules', 'wpdocs-webnail-modules' ),
                'manage_options',
                'wpdocs-ebtech-modules',
                array( __CLASS__, 'menuPage' ),
                'dashicons-tagcloud',
                6
            );
        }
    
        public static function menuPage() {
            if ( is_file( plugin_dir_path( __FILE__ ) . 'includes/layout.php' ) ) {
                include_once plugin_dir_path( __FILE__ ) . 'includes/layout.php';
            }
        }
    
        public static function getSettings() {
            return get_option( 'wpdocs_ebtech_modules_option' );
        }
    
        public static function adminAssets() {
            if ( isset( $_GET['page'] ) && ! empty( $_GET['page'] ) && 'wpdocs-ebtech-modules' === $_GET['page'] ) {
    
            }
        }
    }
    
    WPDocs_EB_EbtechModules::init();
    WPDocs_EB_EbtechModules::getSettings();
  • 示例8

    用于显示页面内容的回调函数不一定需要检查当前用户的能力,因为如果用户没有正确的能力,回调甚至不会连接。

    如果您试图直接访问一个您没有所需能力的页面,您将得到一个错误页面。

  • 示例9
    // For those who are object orientated. Add a class 
    // function as the menu callback and setup the 
    // menus automatically. 
    
    // Exit if accessed directly
    if ( !defined( 'ABSPATH' ) ) exit;
    
    class MyMenuSetterUpper {
    
        private static $instance;
    
        /**
         * Main Instance
         *
         * @staticvar 	array 	$instance
         * @return 		The one true instance
         */
        public static function instance() {
             if ( ! isset( self::$instance ) ) {
                 self::$instance = new self;
    	     self::$instance->addMyAdminMenu();
    	}
    
            return self::$instance;
        }
    
        public function addMyAdminMenu() {
             
             add_menu_page(
                'My Page Title',
                'My Page',
                'read',
                'my-menu-page-slug',
                array(
                    $this,
                    'myAdminPage'
                ),
                'to/icon/file.svg',
                '2.1'
            );
        }
    
        public function myAdminPage() {
             // Echo the html here...
        }
    
    }
    // Call the class and add the menus automatically. 
    $MyMenuSetterUpper = MyMenuSetterUpper::instance();