大家好,今天咱们来聊聊 WordPress 里一个神奇的函数 add_meta_box()
。这货可是定制文章编辑界面,添加自定义元数据框的利器。想象一下,你想在写博客的时候,加个“心情指数”的选项,或者给旅游攻略文章加个“推荐指数”的评价,靠它就对了!
咱们先来热身一下,看看 add_meta_box()
的庐山真面目:
<?php
/**
* 添加自定义元数据框
*
* @param string $id 元数据框的 ID。必须是唯一的。
* @param string $title 元数据框的标题。
* @param callable $callback 显示元数据框内容的函数。
* @param string $screen (可选)在哪个屏幕上显示元数据框。可以是单个屏幕 ID、屏幕 ID 数组或屏幕对象。默认值为当前屏幕。
* @param string $context (可选)元数据框的上下文。可以是 'normal'、'advanced' 或 'side'。默认值为 'advanced'。
* @param string $priority (可选)元数据框的优先级。可以是 'high'、'core'、'default' 或 'low'。默认值为 'default'。
* @param array $callback_args (可选) 传递给回调函数的额外参数。
*/
function add_meta_box( string $id, string $title, callable $callback, string|array|WP_Screen|null $screen = null, string $context = 'advanced', string $priority = 'default', array $callback_args = array() ) {
global $wp_meta_boxes;
$screen = get_current_screen();
if ( is_string( $screen ) ) {
$screen = convert_to_screen( $screen );
} elseif ( is_null( $screen ) ) {
$screen = get_current_screen();
}
if ( ! is_object( $screen ) ) {
return;
}
$page = $screen->id;
// Normalize context to lower case.
$context = strtolower( $context );
if ( ! isset( $wp_meta_boxes ) ) {
$wp_meta_boxes = array();
}
if ( ! isset( $wp_meta_boxes[ $page ] ) ) {
$wp_meta_boxes[ $page ] = array();
}
if ( ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
$wp_meta_boxes[ $page ][ $context ] = array();
}
if ( ! isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
$wp_meta_boxes[ $page ][ $context ][ $priority ] = array();
}
$wp_meta_boxes[ $page ][ $context ][ $priority ][ $id ] = array(
'id' => $id,
'title' => $title,
'callback' => $callback,
'args' => $callback_args,
);
}
看起来参数挺多,别怕!咱们一个个拆解:
参数 | 类型 | 描述 | 例子 |
---|---|---|---|
$id |
string | 元数据框的唯一 ID,就像你的身份证号,绝对不能重复! | 'my_custom_meta_box' |
$title |
string | 元数据框的标题,就是显示在框框顶部的文字。 | '我的自定义元数据框' |
$callback |
callable | 一个函数,用来生成元数据框的内容。这个函数里,你可以放各种 HTML 元素,比如输入框、下拉菜单等等。 | 'my_meta_box_callback' |
$screen |
string|array|WP_Screen|null | 指定在哪个页面显示元数据框。可以是文章类型(post、page)、自定义文章类型,或者一个 WP_Screen 对象。默认是当前页面。 |
'post' ,'my_custom_post_type' |
$context |
string | 元数据框的位置。有三个选项:'normal' (正常位置,在编辑器下方),'advanced' (高级位置,和正常位置一样),'side' (侧边栏)。 |
'normal' ,'side' |
$priority |
string | 元数据框的优先级。有四个选项:'high' (高优先级,靠上显示),'core' (核心优先级,一般不用),'default' (默认优先级),'low' (低优先级,靠下显示)。 |
'high' ,'low' |
$callback_args |
array | 传递给 $callback 函数的额外参数。 |
array('key' => 'value') |
咱们来举个栗子:
假设我们想给文章添加一个“作者心情”的元数据框,让作者可以选择“开心”、“一般”、“郁闷”三种心情。
首先,我们需要定义一个回调函数,用来生成元数据框的内容:
<?php
function my_meta_box_callback( $post ) {
// 添加一个 nonce 字段,用于安全验证
wp_nonce_field( basename(__FILE__), 'my_meta_box_nonce' );
// 获取之前保存的作者心情
$author_mood = get_post_meta( $post->ID, '_author_mood', true );
// 如果没有保存过,就设置一个默认值
if ( empty( $author_mood ) ) {
$author_mood = '一般';
}
// 生成下拉菜单
echo '<label for="author_mood">作者心情:</label>';
echo '<select name="author_mood" id="author_mood">';
echo '<option value="开心"' . selected( $author_mood, '开心', false ) . '>开心</option>';
echo '<option value="一般"' . selected( $author_mood, '一般', false ) . '>一般</option>';
echo '<option value="郁闷"' . selected( $author_mood, '郁闷', false ) . '>郁闷</option>';
echo '</select>';
}
这个函数做了几件事:
- 添加 nonce 字段: 这是为了安全起见,防止跨站请求伪造(CSRF)攻击。
- 获取之前保存的作者心情:
get_post_meta()
函数可以获取文章的元数据。我们使用'_author_mood'
作为键名,存储作者的心情。 - 生成下拉菜单: 使用 HTML 的
<select>
元素生成一个下拉菜单,让作者选择心情。selected()
函数可以根据之前保存的值,自动选中对应的选项。
接下来,我们需要使用 add_meta_box()
函数,将这个元数据框添加到文章编辑界面:
<?php
function add_my_meta_box() {
add_meta_box(
'my_meta_box_id', // ID,唯一标识符
'作者心情', // 标题
'my_meta_box_callback', // 回调函数
'post', // 在文章类型为 post 的页面显示
'side', // 位置:侧边栏
'high' // 优先级:高
);
}
add_action( 'add_meta_boxes', 'add_my_meta_box' );
这个函数做了两件事:
- 调用
add_meta_box()
函数: 传入各个参数,将元数据框添加到文章编辑界面。 - 使用
add_action()
函数: 将add_my_meta_box()
函数挂载到add_meta_boxes
这个钩子上。WordPress 会在适当的时候调用这个函数,从而添加我们的元数据框。
最后,我们需要保存用户选择的心情:
<?php
function save_my_meta_box_data( $post_id ) {
// 检查 nonce 字段
if ( ! isset( $_POST['my_meta_box_nonce'] ) || ! wp_verify_nonce( $_POST['my_meta_box_nonce'], basename(__FILE__) ) ) {
return;
}
// 检查用户是否有权限
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
// 检查是否是自动保存
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// 获取用户选择的心情
if ( isset( $_POST['author_mood'] ) ) {
$author_mood = sanitize_text_field( $_POST['author_mood'] );
// 保存心情
update_post_meta( $post_id, '_author_mood', $author_mood );
}
}
add_action( 'save_post', 'save_my_meta_box_data' );
这个函数做了几件事:
- 检查 nonce 字段: 验证请求的合法性。
- 检查用户权限: 确保用户有权限编辑文章。
- 检查是否是自动保存: 如果是自动保存,就直接返回,不进行保存操作。
- 获取用户选择的心情: 使用
sanitize_text_field()
函数对用户输入进行安全过滤。 - 保存心情: 使用
update_post_meta()
函数将用户选择的心情保存到文章的元数据中。
把这些代码放到你的主题的 functions.php
文件中,或者放到一个自定义插件中,刷新一下文章编辑页面,你就能看到一个“作者心情”的元数据框了!
源码剖析:
现在,咱们深入 add_meta_box()
的源码,看看它到底做了些什么:
-
获取当前屏幕:
<?php $screen = get_current_screen(); if ( is_string( $screen ) ) { $screen = convert_to_screen( $screen ); } elseif ( is_null( $screen ) ) { $screen = get_current_screen(); } if ( ! is_object( $screen ) ) { return; } $page = $screen->id;
这段代码首先获取当前屏幕的
WP_Screen
对象。WP_Screen
对象包含了当前页面的各种信息,比如页面 ID、文章类型等等。如果$screen
是一个字符串(比如文章类型),就使用convert_to_screen()
函数将其转换为WP_Screen
对象。 如果获取不到WP_Screen
对象,就直接返回,不进行任何操作。 -
规范化上下文:
<?php $context = strtolower( $context );
将
$context
参数转换为小写,确保后续的逻辑能够正确处理。 -
存储元数据框信息:
<?php global $wp_meta_boxes; if ( ! isset( $wp_meta_boxes ) ) { $wp_meta_boxes = array(); } if ( ! isset( $wp_meta_boxes[ $page ] ) ) { $wp_meta_boxes[ $page ] = array(); } if ( ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) { $wp_meta_boxes[ $page ][ $context ] = array(); } if ( ! isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) { $wp_meta_boxes[ $page ][ $context ][ $priority ] = array(); } $wp_meta_boxes[ $page ][ $context ][ $priority ][ $id ] = array( 'id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $callback_args, );
这段代码是
add_meta_box()
函数的核心。它使用一个全局变量$wp_meta_boxes
,将元数据框的信息存储起来。$wp_meta_boxes
是一个多维数组,它的结构如下:$wp_meta_boxes[ 页面 ID ][ 上下文 ][ 优先级 ][ 元数据框 ID ] = 元数据框信息数组
元数据框信息数组包含了元数据框的 ID、标题、回调函数和额外参数。
add_meta_box()
函数只是将元数据框的信息存储起来,并没有真正地将元数据框显示在页面上。真正显示元数据框的是do_meta_boxes()
函数。
do_meta_boxes()
函数:
do_meta_boxes()
函数负责在页面上显示元数据框。它的定义如下:
<?php
/**
* 显示元数据框
*
* @param string|WP_Screen $screen 当前屏幕。
* @param string $context 元数据框的上下文。
* @param WP_Post|null $post (可选)当前文章对象。
*/
function do_meta_boxes( $screen, $context, $post = null ) {
global $wp_meta_boxes;
if ( is_string( $screen ) || is_object( $screen ) ) {
$screen = convert_to_screen( $screen );
}
$page = $screen->id;
if ( empty( $wp_meta_boxes[ $page ][ $context ] ) ) {
return;
}
$priority_order = array( 'high', 'core', 'default', 'low' );
foreach ( $priority_order as $priority ) {
if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
foreach ( (array) $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
call_user_func( $box['callback'], $post, $box['args'] );
}
}
}
}
这个函数做了几件事:
- 获取页面 ID: 和
add_meta_box()
函数一样,首先获取当前页面的 ID。 - 检查是否有元数据框: 如果当前页面和上下文中没有元数据框,就直接返回。
- 遍历优先级: 按照
high
、core
、default
、low
的顺序遍历优先级。 - 遍历元数据框: 遍历当前优先级下的所有元数据框。
- 调用回调函数: 调用元数据框的回调函数,生成元数据框的内容。
do_meta_boxes()
函数会在 WordPress 的模板文件中被调用,从而将元数据框显示在页面上。
总结:
add_meta_box()
函数和 do_meta_boxes()
函数是 WordPress 中自定义元数据框的核心。add_meta_box()
函数负责注册元数据框,将元数据框的信息存储起来。do_meta_boxes()
函数负责显示元数据框,调用元数据框的回调函数生成元数据框的内容。
高级用法:
除了基本的用法之外,add_meta_box()
函数还有一些高级用法:
- 使用
WP_Screen
对象: 可以使用WP_Screen
对象来指定在哪个页面显示元数据框。例如,可以使用get_current_screen()
函数获取当前页面的WP_Screen
对象,然后将其传递给add_meta_box()
函数。 - 传递额外参数: 可以使用
$callback_args
参数将额外参数传递给回调函数。例如,可以传递一个数组,包含一些配置信息。 - 使用自定义文章类型: 可以将元数据框添加到自定义文章类型中。只需要将
$screen
参数设置为自定义文章类型的名称即可。 - 使用不同的上下文: 可以使用不同的上下文来控制元数据框的位置。例如,可以使用
'side'
上下文将元数据框添加到侧边栏。
注意事项:
- ID 必须唯一: 每个元数据框的 ID 必须是唯一的,否则会导致冲突。
- 安全验证: 在保存元数据时,一定要进行安全验证,防止跨站请求伪造(CSRF)攻击。
- 清理用户输入: 在保存用户输入之前,一定要对其进行清理,防止恶意代码注入。
希望今天的讲解能够帮助你更好地理解 WordPress 的 add_meta_box()
函数。掌握了它,你就可以自由地定制文章编辑界面,添加各种自定义元数据框,让你的网站更加个性化!
下次有机会,咱们再聊聊如何使用 JavaScript 和 CSS 来美化元数据框,让它们看起来更漂亮!