do_meta_boxes()
云策文档标注
概述
do_meta_boxes() 是 WordPress 中用于输出所有已注册到特定页面和上下文的元框(meta box)的模板函数。它处理元框的排序、隐藏状态以及与块编辑器的兼容性,并返回显示的元框数量。
关键要点
- 函数参数:$screen(屏幕标识符,必需,可以是字符串或 WP_Screen 对象)、$context(屏幕上下文,必需)、$data_object(传递给元框回调函数的数据对象,必需)。
- 功能:输出通过 add_meta_box() 注册的元框,支持优先级排序(high、sorted、core、default、low)和用户自定义排序。
- 兼容性处理:自动检测元框与块编辑器的兼容性,不兼容时可能替换回调函数或显示警告。
- 返回值:整数,表示显示的元框数量。
- 相关函数:包括 add_meta_box()、get_hidden_meta_boxes()、convert_to_screen() 等。
代码示例
function adding_custom_meta_boxes() {
add_meta_box(
'meta_box_id',
__( 'Title of the Metabox' ),
'callback_metabox_function',
'my_custom_menu_page' );
}
add_action( 'add_meta_boxes', 'adding_custom_meta_boxes', 10, 2 );
function callback_metabox_function(){
echo 'Metabox Content';
}
do_meta_boxes( 'my_custom_menu_page', 'normal', '' );注意事项
- 确保 $screen 参数符合 sanitize_key() 限制,否则可能无法正确渲染。
- 元框排序可通过动态钩子 get_user_option_meta-box-order_[page] 进行自定义。
- 在块编辑器环境中,不兼容的元框可能被隐藏或替换,需注意兼容性设置。
原文内容
Meta-Box template function.
Parameters
$screenstring|WP_Screenrequired-
The screen identifier. If you have used add_menu_page() or add_submenu_page() to create a new screen (and hence screen_id) make sure your menu slug conforms to the limits of sanitize_key() otherwise the
'screen'menu may not correctly render on your page. $contextstringrequired-
The screen context for which to display meta boxes.
$data_objectmixedrequired-
Gets passed to the meta box callback function as the first parameter.
Often this is the object that’s the focus of the current screen, for example aWP_PostorWP_Commentobject.
Source
function do_meta_boxes( $screen, $context, $data_object ) {
global $wp_meta_boxes;
static $already_sorted = false;
if ( empty( $screen ) ) {
$screen = get_current_screen();
} elseif ( is_string( $screen ) ) {
$screen = convert_to_screen( $screen );
}
$page = $screen->id;
$hidden = get_hidden_meta_boxes( $screen );
printf( '<div id="%s-sortables" class="meta-box-sortables">', esc_attr( $context ) );
/*
* Grab the ones the user has manually sorted.
* Pull them out of their previous context/priority and into the one the user chose.
*/
$sorted = get_user_option( "meta-box-order_$page" );
if ( ! $already_sorted && $sorted ) {
foreach ( $sorted as $box_context => $ids ) {
foreach ( explode( ',', $ids ) as $id ) {
if ( $id && 'dashboard_browser_nag' !== $id ) {
add_meta_box( $id, null, null, $screen, $box_context, 'sorted' );
}
}
}
}
$already_sorted = true;
$i = 0;
if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
foreach ( array( 'high', 'sorted', 'core', 'default', 'low' ) as $priority ) {
if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
foreach ( (array) $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
if ( false === $box || ! $box['title'] ) {
continue;
}
$block_compatible = true;
if ( is_array( $box['args'] ) ) {
// If a meta box is just here for back compat, don't show it in the block editor.
if ( $screen->is_block_editor() && isset( $box['args']['__back_compat_meta_box'] ) && $box['args']['__back_compat_meta_box'] ) {
continue;
}
if ( isset( $box['args']['__block_editor_compatible_meta_box'] ) ) {
$block_compatible = (bool) $box['args']['__block_editor_compatible_meta_box'];
unset( $box['args']['__block_editor_compatible_meta_box'] );
}
// If the meta box is declared as incompatible with the block editor, override the callback function.
if ( ! $block_compatible && $screen->is_block_editor() ) {
$box['old_callback'] = $box['callback'];
$box['callback'] = 'do_block_editor_incompatible_meta_box';
}
if ( isset( $box['args']['__back_compat_meta_box'] ) ) {
$block_compatible = $block_compatible || (bool) $box['args']['__back_compat_meta_box'];
unset( $box['args']['__back_compat_meta_box'] );
}
}
++$i;
// get_hidden_meta_boxes() doesn't apply in the block editor.
$hidden_class = ( ! $screen->is_block_editor() && in_array( $box['id'], $hidden, true ) ) ? ' hide-if-js' : '';
echo '<div id="' . $box['id'] . '" class="postbox ' . postbox_classes( $box['id'], $page ) . $hidden_class . '" ' . '>' . "n";
echo '<div class="postbox-header">';
echo '<h2 class="hndle">';
if ( 'dashboard_php_nag' === $box['id'] ) {
echo '<span aria-hidden="true" class="dashicons dashicons-warning"></span>';
echo '<span class="screen-reader-text">' .
/* translators: Hidden accessibility text. */
__( 'Warning:' ) .
' </span>';
}
echo $box['title'];
echo "</h2>n";
if ( 'dashboard_browser_nag' !== $box['id'] ) {
$widget_title = $box['title'];
if ( is_array( $box['args'] ) && isset( $box['args']['__widget_basename'] ) ) {
$widget_title = $box['args']['__widget_basename'];
// Do not pass this parameter to the user callback function.
unset( $box['args']['__widget_basename'] );
}
echo '<div class="handle-actions hide-if-no-js">';
echo '<button type="button" class="handle-order-higher" aria-disabled="false" aria-describedby="' . $box['id'] . '-handle-order-higher-description">';
echo '<span class="screen-reader-text">' .
/* translators: Hidden accessibility text. */
__( 'Move up' ) .
'</span>';
echo '<span class="order-higher-indicator" aria-hidden="true"></span>';
echo '</button>';
echo '<span class="hidden" id="' . $box['id'] . '-handle-order-higher-description">' . sprintf(
/* translators: %s: Meta box title. */
__( 'Move %s box up' ),
$widget_title
) . '</span>';
echo '<button type="button" class="handle-order-lower" aria-disabled="false" aria-describedby="' . $box['id'] . '-handle-order-lower-description">';
echo '<span class="screen-reader-text">' .
/* translators: Hidden accessibility text. */
__( 'Move down' ) .
'</span>';
echo '<span class="order-lower-indicator" aria-hidden="true"></span>';
echo '</button>';
echo '<span class="hidden" id="' . $box['id'] . '-handle-order-lower-description">' . sprintf(
/* translators: %s: Meta box title. */
__( 'Move %s box down' ),
$widget_title
) . '</span>';
echo '<button type="button" class="handlediv" aria-expanded="true">';
echo '<span class="screen-reader-text">' . sprintf(
/* translators: %s: Hidden accessibility text. Meta box title. */
__( 'Toggle panel: %s' ),
$widget_title
) . '</span>';
echo '<span class="toggle-indicator" aria-hidden="true"></span>';
echo '</button>';
echo '</div>';
}
echo '</div>';
echo '<div class="inside">' . "n";
if ( WP_DEBUG && ! $block_compatible && 'edit' === $screen->parent_base && ! $screen->is_block_editor() && ! isset( $_GET['meta-box-loader'] ) ) {
$plugin = _get_plugin_from_callback( $box['callback'] );
if ( $plugin ) {
$meta_box_not_compatible_message = sprintf(
/* translators: %s: The name of the plugin that generated this meta box. */
__( 'This meta box, from the %s plugin, is not compatible with the block editor.' ),
"<strong>{$plugin['Name']}</strong>"
);
wp_admin_notice(
$meta_box_not_compatible_message,
array(
'additional_classes' => array( 'error', 'inline' ),
)
);
}
}
call_user_func( $box['callback'], $data_object, $box );
echo "</div>n";
echo "</div>n";
}
}
}
}
echo '</div>';
return $i;
}
Changelog
| Version | Description |
|---|---|
| 2.5.0 | Introduced. |
Skip to note 5 content
Farhan Noor
This is how you can register a new meta box, then outputs that meta box using this do_meta_boxes function:
function adding_custom_meta_boxes() { add_meta_box( 'meta_box_id', __( 'Title of the Metabox' ), 'callback_metabox_function', 'my_custom_menu_page' ); } add_action( 'add_meta_boxes', 'adding_custom_meta_boxes', 10, 2 ); function callback_metabox_function(){ echo 'Metabox Content'; } do_meta_boxes( 'my_custom_menu_page', 'normal', '' );Skip to note 6 content
ramon fincken
When wanting to change the order of metaboxes there is an undocumented (I could not find it at WP.org) filter you can use.
get_user_option_meta-box-order_[CUSTOM_POST_TYPE]
it will have 1 parameter, the $order array.
For example for the CPT named posts
get_user_option_meta-box-order_post
This is an example to re-order metaboxes (note that this example might differ from your metaboxes)
add_filter( 'get_user_option_meta-box-order_post', 'wpse25793_one_column_for_all' ); function wpse25793_one_column_for_all( $order ) { return array( 'normal' => join( ",", array( 'postexcerpt', 'formatdiv', 'trackbacksdiv', 'tagsdiv-post_tag', 'categorydiv', 'postimagediv', 'postcustom', 'commentstatusdiv', 'slugdiv', 'authordiv', 'submitdiv', ) ), 'side' => '', 'advanced' => '', ); }Source: http://wordpress.stackexchange.com/questions/25793/how-to-force-one-column-layout-on-custom-post-type-edit-page/25814#25814
Skip to note 7 content
Drew Jaynes
Worth mentioning that the ‘get_user_option_meta-box-order_post’ hook referenced in @ramon fincken’s example is “undocumented” only because it’s a dynamic hook, specifically the get_user_option_{$option} hook, where “meta-box-order” is a specific user option. Cool tip though 🙂
Skip to note 8 content
Codex
Example
Here is an example that uses add_meta_box to register a new meta box, then outputs that meta box using this do_meta_boxes function:
add_meta_box( 'my-custom-meta-box', __( 'My Custom Meta Box', 'textdomain' ), 'my_custom_menu_page', 'normal' ); do_meta_boxes( 'my_custom_menu_page', 'normal', '' );