在 WordPress 中删除导航菜单时重置自定义字段
reset custom field when navigation menu is deleted in WordPress
我有一个与所有帖子和页面关联的自定义字段。它是所有导航菜单的下拉菜单。
这是我填充自定义字段下拉列表的方式:(字段名称是 custom_menu...)
function acf_load_menu_field_choices( $field ) {
// reset choices
$field['choices'] = array();
$menus = get_terms( 'nav_menu', array( 'hide_empty' => true ) );
$blank_list = json_encode(array( "name" => "Select Menu", "slug" => ""));
$blank_list = json_decode($blank_list);
array_unshift($menus, $blank_list);
foreach ( $menus as $val ) {
$value = $val->slug;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
// return the field
return $field;
}
add_filter('acf/load_field/name=custom_menu', 'acf_load_menu_field_choices');
这是我在每个页面上使用的常用菜单位置:
function register_custom_menu() { //function to register new menu
register_nav_menu('custom-menu',__( 'Custom Menu' ));
}
add_action( 'init', 'register_custom_menu' );
然后我根据每个页面上的自定义字段菜单将菜单动态分配到位置 custom-menu
。
这里是加载每个页面时触发的函数:
add_action("wp_ajax_load_custom_menu", "load_custom_menu");
add_action("wp_ajax_nopriv_load_custom_menu", "load_custom_menu");
function load_custom_menu(){
$post_id = $_POST['page_id'];
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == "primary") return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('slug', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
set_theme_mod('nav_menu_locations', $locations);
wp_nav_menu( array(
'theme_location' => 'custom-menu',
'menu_id' => 'primary-menu',
'menu_class' => 'main-nav underline-decoration l-to-r-line level-arrows-on outside-item-remove-margin',
'container' => false
)
);
wp_die();
}
此 ajax 函数在 ready
事件上触发并接收一个名为 page_id
的 POST
值。此函数检查 custom-menu
的给定 page_id
的自定义字段值,并将该菜单分配给名为 custom-menu
.
的 menu location
这是我的 JavaScript 以备不时之需:
jQuery(document).ready( function($){
let customMenu;
let page_id = script_vars.postID;
$.post(dtLocal.ajaxurl, { action: "load_custom_menu", page_id: page_id }, resp => customMenu = resp);
$(window).scroll(() => {
if(customMenu !== "0"){
$("#phantom .main-nav").remove();
$("#phantom .menu-box").html(customMenu);
}
})
})
这就是我的代码的工作方式,到目前为止一切正常。
问题来了
每当我从 Appearence>Menus>Delete Menu 中删除导航菜单时,我的自定义菜单开始出现意外行为,因为自定义字段值仍指向已删除的菜单。
我想在这里做的是,我想在删除菜单时删除自定义字段。 首先,我想获取已删除菜单的 slug,然后找到带有该 slug 的自定义字段值,最后,删除或重置该自定义字段。
您正在寻找需要一个参数的操作 wp_delete_nav_menu
- menu id
。那个时候你的导航菜单将被删除的问题,所以你将无法接受它。
如果您可以存储导航菜单 ID 而不是 slug,那将大大简化事情。
在acf_load_menu_field_choices
中替换:
foreach ( $menus as $val ) {
$value = $val->term_id;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
在load_custom_menu
中:
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == /* Should be your primary menu ID */) return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('id', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
完成这些更改后,您需要重写 custom_menu
全部 posts\pages。
之后,当您删除菜单时,以下函数将删除所有相关字段。它仅在典型的 ACF 字段(字符串)而不是自定义字段上进行了测试,但应该也能很好地处理您的代码。
add_action('wp_delete_nav_menu', 'delete_all_acf_fields_with_menu', 10, 1);
function delete_all_acf_fields_with_menu($term_id) {
$args = array(
'post_type' => array('post', 'page'),
'posts_per_page' => -1,
'meta_key' => 'custom_menu',
'meta_value' => $term_id,
);
$posts = get_posts($args);
if( $posts ) {
foreach( $posts as $p ) {
delete_field('custom_menu', $p->ID);
}
}
}
WordPress 中的菜单只是 terms in a taxonomy。所以你可以使用所有的钩子这个术语。
特别是 pre_delete_term 挂钩。
add_action( 'pre_delete_term', 'my_func' );
function my_func($term, $taxonomy){
// Check the taxonomy is really 'menu', then check term
}
我有一个与所有帖子和页面关联的自定义字段。它是所有导航菜单的下拉菜单。 这是我填充自定义字段下拉列表的方式:(字段名称是 custom_menu...)
function acf_load_menu_field_choices( $field ) {
// reset choices
$field['choices'] = array();
$menus = get_terms( 'nav_menu', array( 'hide_empty' => true ) );
$blank_list = json_encode(array( "name" => "Select Menu", "slug" => ""));
$blank_list = json_decode($blank_list);
array_unshift($menus, $blank_list);
foreach ( $menus as $val ) {
$value = $val->slug;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
// return the field
return $field;
}
add_filter('acf/load_field/name=custom_menu', 'acf_load_menu_field_choices');
这是我在每个页面上使用的常用菜单位置:
function register_custom_menu() { //function to register new menu
register_nav_menu('custom-menu',__( 'Custom Menu' ));
}
add_action( 'init', 'register_custom_menu' );
然后我根据每个页面上的自定义字段菜单将菜单动态分配到位置 custom-menu
。
这里是加载每个页面时触发的函数:
add_action("wp_ajax_load_custom_menu", "load_custom_menu");
add_action("wp_ajax_nopriv_load_custom_menu", "load_custom_menu");
function load_custom_menu(){
$post_id = $_POST['page_id'];
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == "primary") return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('slug', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
set_theme_mod('nav_menu_locations', $locations);
wp_nav_menu( array(
'theme_location' => 'custom-menu',
'menu_id' => 'primary-menu',
'menu_class' => 'main-nav underline-decoration l-to-r-line level-arrows-on outside-item-remove-margin',
'container' => false
)
);
wp_die();
}
此 ajax 函数在 ready
事件上触发并接收一个名为 page_id
的 POST
值。此函数检查 custom-menu
的给定 page_id
的自定义字段值,并将该菜单分配给名为 custom-menu
.
menu location
这是我的 JavaScript 以备不时之需:
jQuery(document).ready( function($){
let customMenu;
let page_id = script_vars.postID;
$.post(dtLocal.ajaxurl, { action: "load_custom_menu", page_id: page_id }, resp => customMenu = resp);
$(window).scroll(() => {
if(customMenu !== "0"){
$("#phantom .main-nav").remove();
$("#phantom .menu-box").html(customMenu);
}
})
})
这就是我的代码的工作方式,到目前为止一切正常。
问题来了 每当我从 Appearence>Menus>Delete Menu 中删除导航菜单时,我的自定义菜单开始出现意外行为,因为自定义字段值仍指向已删除的菜单。 我想在这里做的是,我想在删除菜单时删除自定义字段。 首先,我想获取已删除菜单的 slug,然后找到带有该 slug 的自定义字段值,最后,删除或重置该自定义字段。
您正在寻找需要一个参数的操作 wp_delete_nav_menu
- menu id
。那个时候你的导航菜单将被删除的问题,所以你将无法接受它。
如果您可以存储导航菜单 ID 而不是 slug,那将大大简化事情。
在acf_load_menu_field_choices
中替换:
foreach ( $menus as $val ) {
$value = $val->term_id;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
在load_custom_menu
中:
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == /* Should be your primary menu ID */) return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('id', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
完成这些更改后,您需要重写 custom_menu
全部 posts\pages。
之后,当您删除菜单时,以下函数将删除所有相关字段。它仅在典型的 ACF 字段(字符串)而不是自定义字段上进行了测试,但应该也能很好地处理您的代码。
add_action('wp_delete_nav_menu', 'delete_all_acf_fields_with_menu', 10, 1);
function delete_all_acf_fields_with_menu($term_id) {
$args = array(
'post_type' => array('post', 'page'),
'posts_per_page' => -1,
'meta_key' => 'custom_menu',
'meta_value' => $term_id,
);
$posts = get_posts($args);
if( $posts ) {
foreach( $posts as $p ) {
delete_field('custom_menu', $p->ID);
}
}
}
WordPress 中的菜单只是 terms in a taxonomy。所以你可以使用所有的钩子这个术语。
特别是 pre_delete_term 挂钩。
add_action( 'pre_delete_term', 'my_func' );
function my_func($term, $taxonomy){
// Check the taxonomy is really 'menu', then check term
}