各位观众老爷,晚上好!我是你们今晚的WordPress源码深度游导游,咱们今天的主题是:深扒add_menu_page()
这个家伙,看看它到底是怎么把顶级菜单塞进WordPress后台的。
准备好了吗?Let’s dive in!
一、初识add_menu_page()
:长得好看但你得懂
首先,我们来看看add_menu_page()
长什么样,别光看脸,还得看内在:
add_menu_page(
string $page_title,
string $menu_title,
string $capability,
string $menu_slug,
callable $function = '',
string $icon_url = '',
int $position = null
);
是不是感觉有点头大?别怕,我来给它翻译翻译:
$page_title
: 页面标题,显示在浏览器标签栏和编辑页面顶部。 可以理解为“这页纸的抬头”。$menu_title
: 菜单标题,显示在WordPress后台的菜单栏。 也就是左边竖着那一溜的文字。$capability
: 权限,决定谁能看到这个菜单。 比如'manage_options'
只有管理员才能看到。$menu_slug
: 菜单别名,用于生成URL,也是唯一标识符。 相当于身份证号。$function
: 回调函数,点击菜单后执行的函数,显示页面内容。 就是菜单点开后,你要展示什么东西。$icon_url
: 菜单图标URL,可以是Dashicons或者自定义图标。 让你的菜单看起来更漂亮。$position
: 菜单位置,决定菜单在菜单栏的排序。 数字越小越靠前。
简单来说,就是告诉WordPress:
"喂,WordPress,我要加个菜单! 抬头是
$page_title
,名字是$menu_title
, 只有$capability
权限的人才能看, 链接是$menu_slug
, 点开后执行$function
, 图标用$icon_url
, 放在第$position
个位置。"
二、add_menu_page()
背后的故事:源码解读
光知道add_menu_page()
怎么用还不够,我们要深入源码,看看它是怎么运作的。 别担心,我不会直接丢给你一堆代码让你自己啃,我会抽丝剥茧,把重要的部分拎出来讲。
-
入口:
add_menu_page()
只是个皮包公司实际上,
add_menu_page()
自己啥也不干,它只是调用了add_submenu_page()
函数,并且把$menu_slug
设置成了null
。 这就有点像个中介,把任务转手给了别人。源码片段:
function add_menu_page( string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '', string $icon_url = '', int $position = null ) { global $menu, $submenu; $menu_slug = plugin_basename( $menu_slug ); add_submenu_page( $menu_slug, $page_title, $menu_title, $capability, $menu_slug, $function, $position ); return true; }
注意
add_submenu_page( $menu_slug, $page_title, $menu_title, $capability, $menu_slug, $function, $position );
这里,$menu_slug
竟然又作为第一个参数传递了进去,这是为什么呢? 别急,我们接着往下看add_submenu_page()
的源码。 -
核心:
add_submenu_page()
才是真大佬add_submenu_page()
负责将菜单项添加到全局变量$menu
和$submenu
中。 这两个全局变量存储了WordPress后台菜单的所有信息。$menu
: 是一个二维数组,存储顶级菜单的信息。$submenu
: 是一个三维数组,存储子菜单的信息。 第一层是父菜单的$menu_slug
,第二层是子菜单的索引,第三层是子菜单的详细信息。源码片段(简化版):
function add_submenu_page( string $parent_slug, string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '', int $position = null ) { global $menu, $submenu, $_wp_real_parent_file; $menu_slug = plugin_basename( $menu_slug ); $parent_slug = plugin_basename( $parent_slug ); // ... 一堆参数检查和处理 ... // 如果 $parent_slug 为 null,则表示添加顶级菜单 if ( null === $parent_slug ) { // 找到合适的位置插入菜单 if ( null === $position ) { $menu[] = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $menu_slug, $hookname, $icon_url ); } else { $menu[ $position ] = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $menu_slug, $hookname, $icon_url ); } } else { // 添加子菜单 $submenu[ $parent_slug ][] = array( $menu_title, $capability, $menu_slug, $page_title ); } // ... 其他处理 ... return $hookname; }
重点解析:
-
if ( null === $parent_slug )
: 这是判断是否添加顶级菜单的关键。 因为add_menu_page()
会将$menu_slug
设置为null
,所以会进入这个分支。 -
$menu[] = array(...)
: 将菜单信息添加到$menu
数组中。$menu
数组的每个元素都是一个数组,包含了菜单的标题、权限、别名、页面标题、CSS类、钩子名称和图标URL。 -
$submenu[ $parent_slug ][] = array(...)
: 如果$parent_slug
不为null
,则表示添加子菜单。 子菜单的信息会被添加到$submenu
数组中,以父菜单的$menu_slug
作为键。 -
$hookname
: 这个非常重要,它是一个钩子名称,用于在菜单页面加载时执行回调函数。 WordPress会根据这个钩子名称来调用我们传入的$function
。
-
-
钩子的力量:
load-{$hookname}
还记得
add_submenu_page()
返回的$hookname
吗? 它可不是摆设,而是连接菜单和回调函数的关键。WordPress会使用
add_action()
函数,将回调函数绑定到load-{$hookname}
这个钩子上。 当用户点击菜单,页面即将加载时,这个钩子会被触发,回调函数就会被执行。源码片段:
add_action( "load-$hookname", $function );
也就是说,当用户点击菜单时,WordPress会:
- 加载菜单对应的页面。
- 触发
load-{$hookname}
钩子。 - 执行我们提供的
$function
回调函数,显示页面内容。
三、实战演练:手撸一个顶级菜单
理论讲了一堆,不如撸起袖子干一把。 我们来创建一个简单的顶级菜单,显示一个“Hello World”页面。
<?php
/**
* Plugin Name: My Awesome Menu
* Description: Adds a top-level menu to the WordPress admin.
*/
// 添加菜单
add_action( 'admin_menu', 'my_awesome_menu' );
function my_awesome_menu() {
add_menu_page(
'My Awesome Page Title', // 页面标题
'My Awesome Menu', // 菜单标题
'manage_options', // 权限
'my-awesome-menu', // 菜单别名
'my_awesome_page_content', // 回调函数
'dashicons-star-filled', // 图标
20 // 位置
);
}
// 页面内容
function my_awesome_page_content() {
echo '<h1>Hello World!</h1>';
echo '<p>This is my awesome menu page!</p>';
}
代码解释:
-
add_action( 'admin_menu', 'my_awesome_menu' );
: 在admin_menu
钩子上注册my_awesome_menu
函数。admin_menu
钩子会在WordPress后台菜单加载时触发。 -
my_awesome_menu()
: 使用add_menu_page()
添加菜单。 -
my_awesome_page_content()
: 回调函数,显示“Hello World”页面。
安装并激活这个插件,你就会在WordPress后台看到一个名为“My Awesome Menu”的顶级菜单,点击后会显示“Hello World!”页面。
四、更上一层楼:高级用法
add_menu_page()
的功能远不止于此,我们还可以玩出更多花样。
-
自定义图标:
除了Dashicons,你还可以使用自定义图标。 只需将
$icon_url
设置为图片的URL即可。add_menu_page( 'My Awesome Page Title', 'My Awesome Menu', 'manage_options', 'my-awesome-menu', 'my_awesome_page_content', plugin_dir_url( __FILE__ ) . 'images/my-icon.png', // 自定义图标URL 20 );
-
动态菜单位置:
你可以根据不同的条件,动态设置菜单的位置。
$position = get_option( 'my_menu_position', 20 ); // 从数据库获取位置 add_menu_page( 'My Awesome Page Title', 'My Awesome Menu', 'manage_options', 'my-awesome-menu', 'my_awesome_page_content', 'dashicons-star-filled', $position // 动态位置 );
-
权限控制:
更精细地控制菜单的访问权限。
if ( current_user_can( 'edit_posts' ) ) { // 只有能编辑文章的用户才能看到 add_menu_page( 'My Awesome Page Title', 'My Awesome Menu', 'edit_posts', // 权限 'my-awesome-menu', 'my_awesome_page_content', 'dashicons-star-filled', 20 ); }
五、总结:add_menu_page()
的精髓
我们来总结一下add_menu_page()
的精髓:
- 本质: 它是一个辅助函数,简化了添加顶级菜单的操作。
- 核心: 它调用
add_submenu_page()
函数,将菜单信息添加到全局变量$menu
中。 - 关键: 它使用
load-{$hookname}
钩子,将回调函数绑定到菜单页面加载事件。
表格总结:
函数名 | 作用 | 核心变量 | 关键钩子 |
---|---|---|---|
add_menu_page() |
添加顶级菜单的辅助函数,实际调用add_submenu_page() |
$menu |
load-{$hookname} |
add_submenu_page() |
添加菜单(包括顶级菜单和子菜单)的核心函数,将菜单信息添加到$menu 和$submenu 全局变量中。 |
$menu , $submenu |
load-{$hookname} |
$menu |
存储顶级菜单信息的全局变量,是一个二维数组。 | ||
$submenu |
存储子菜单信息的全局变量,是一个三维数组。 | ||
load-{$hookname} |
菜单页面加载时触发的钩子,用于执行回调函数,显示页面内容。 |
希望今天的讲解能够帮助你更深入地理解add_menu_page()
函数。 记住,源码的世界充满了乐趣,只要你愿意探索,就能发现更多惊喜!
下次再见!