wp_ajax_add_menu_item()
云策文档标注
概述
wp_ajax_add_menu_item() 是一个 WordPress AJAX 处理函数,用于通过 AJAX 请求添加导航菜单项。它验证用户权限、处理菜单项数据,并输出菜单项的 HTML 结构。
关键要点
- 函数通过 check_ajax_referer() 验证 AJAX 请求安全性,并使用 current_user_can('edit_theme_options') 检查用户权限。
- 处理非自定义菜单项(如 post_type、post_type_archive、taxonomy)时,通过 get_post()、get_post_type_object()、get_term() 获取对象数据,并使用 wp_setup_nav_menu_item() 恢复缺失属性。
- 使用 wp_save_nav_menu_items() 保存菜单项数据,并处理可能的 WP_Error。
- 通过 apply_filters('wp_edit_nav_menu_walker') 应用自定义 Walker 类,并使用 walk_nav_menu_tree() 生成菜单项的 HTML 输出。
- 函数在 WordPress 3.1.0 版本中引入。
代码示例
// 示例:处理 AJAX 添加菜单项的核心逻辑片段
foreach ( (array) $_POST['menu-item'] as $menu_item_data ) {
if ( ! empty( $menu_item_data['menu-item-type'] ) && 'custom' !== $menu_item_data['menu-item-type'] ) {
// 根据类型获取对象并设置菜单项
$_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
$_menu_item = reset( $_menu_items );
$menu_item_data['menu-item-description'] = $_menu_item->description;
}
$menu_items_data[] = $menu_item_data;
}注意事项
- 函数依赖于 wp-admin/includes/nav-menu.php 中的相关函数,如 wp_save_nav_menu_items() 和 wp_setup_nav_menu_item()。
- 使用 wp_die() 处理错误或权限不足情况,确保 AJAX 响应正确终止。
- 通过过滤器 wp_edit_nav_menu_walker 允许自定义菜单项的 Walker 类,增强扩展性。
原文内容
Handles adding a menu item via AJAX.
Source
function wp_ajax_add_menu_item() {
check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
if ( ! current_user_can( 'edit_theme_options' ) ) {
wp_die( -1 );
}
require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
/*
* For performance reasons, we omit some object properties from the checklist.
* The following is a hacky way to restore them when adding non-custom items.
*/
$menu_items_data = array();
foreach ( (array) $_POST['menu-item'] as $menu_item_data ) {
if (
! empty( $menu_item_data['menu-item-type'] ) &&
'custom' !== $menu_item_data['menu-item-type'] &&
! empty( $menu_item_data['menu-item-object-id'] )
) {
switch ( $menu_item_data['menu-item-type'] ) {
case 'post_type':
$_object = get_post( $menu_item_data['menu-item-object-id'] );
break;
case 'post_type_archive':
$_object = get_post_type_object( $menu_item_data['menu-item-object'] );
break;
case 'taxonomy':
$_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
break;
}
$_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
$_menu_item = reset( $_menu_items );
// Restore the missing menu item properties.
$menu_item_data['menu-item-description'] = $_menu_item->description;
}
$menu_items_data[] = $menu_item_data;
}
$item_ids = wp_save_nav_menu_items( 0, $menu_items_data );
if ( is_wp_error( $item_ids ) ) {
wp_die( 0 );
}
$menu_items = array();
foreach ( (array) $item_ids as $menu_item_id ) {
$menu_obj = get_post( $menu_item_id );
if ( ! empty( $menu_obj->ID ) ) {
$menu_obj = wp_setup_nav_menu_item( $menu_obj );
$menu_obj->title = empty( $menu_obj->title ) ? __( 'Menu Item' ) : $menu_obj->title;
$menu_obj->label = $menu_obj->title; // Don't show "(pending)" in ajax-added items.
$menu_items[] = $menu_obj;
}
}
/** This filter is documented in wp-admin/includes/nav-menu.php */
$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] );
if ( ! class_exists( $walker_class_name ) ) {
wp_die( 0 );
}
if ( ! empty( $menu_items ) ) {
$args = array(
'after' => '',
'before' => '',
'link_after' => '',
'link_before' => '',
'walker' => new $walker_class_name(),
);
echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
}
wp_die();
}
Hooks
- apply_filters( ‘wp_edit_nav_menu_walker’, string $class, int $menu_id )
-
Filters the Walker class used when adding nav menu items.
Changelog
| Version | Description |
|---|---|
| 3.1.0 | Introduced. |