WordPress不通过插件如何把自定义文章列表动态添加到主菜单中

本站所有文章均为博主人工写作,无AI辅助成分,请放心参阅。

前几天维护一个客户的网站碰到一个需求:网站有一个自定义文章类型Brand,下属有30多篇文章,客户希望这些文章能够自动更新到主菜单名为“Brand”的菜单项下作为子菜单项。因为更新Brand文章的编辑人员在添加文章后容易忘记去更新网站菜单,所以要求这个网站菜单可以自动读取文章列表,这样就不需要手动维护主菜单了。

网站菜单大致就是这样的:
WordPress不通过插件如何把自定义文章列表动态添加到主菜单中-实现效果

查了一下文档,WordPress输出完整菜单的钩子是 wp_nav_menu_objects ,通过改写输出内容,我们就可以在指定的位置插入自己的菜单项,完整代码如下,注释含可参考信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
* Customize menu items, add custom post type posts under specific parent item
* https://blog.brain1981.com
*/
function brain1981_add_posts_to_menu($items, $args) {
	//只对特定的菜单进行处理,根据菜单名或位置调整,‘menu-top’是我对主菜单的命名
	if ($args->theme_location != 'primary' && $args->menu != 'menu-top' && $args->menu_slug != 'menu-top') {
	    return $items;
	}
 
	//查找目标父菜单项,我的父菜单是Brands,菜单ID是21,根据需要修改
	$parent_item = null;
	$parent_item_index = null;
	foreach ($items as $index => $item) {
		if ($item->title == 'Brands' || $item->post_name == 'Brands' || $item->object_id == '21') {
			$parent_item = $item;
			$parent_item_index = $index;
			break;
		}
	}
	//没有找到目标菜单就直接返回
	if (!$parent_item) {
	    return $items;
	}
 
	//获取所有brand文章,如果没有文章,直接返回
	$brand_posts = get_posts(array(
		'post_type' => 'brand',
		'numberposts' => -1,
		'orderby' => 'menu_order title',
		'order' => 'ASC',
		'post_status' => 'publish',
		'suppress_filters' => 0
	));
 
	//没有brand文章直接返回
	if (empty($brand_posts)) {
		return $items;
	}
 
	//为父菜单项添加‘has-children’类,有时候我们需要给父菜单以以样式区别
	if (!in_array('menu-item-has-children', $parent_item->classes)) {
		$parent_item->classes[] = 'menu-item-has-children';
		$items[$parent_item_index] = $parent_item;
	}
 
	//获取当前最大菜单项ID,并且加上一个大数字,这样新生成的菜单项的id不会和已有的重复
	$max_db_id = 0;
	foreach ($items as $item) {
		if ($item->db_id > $max_db_id) {
			$max_db_id = $item->db_id;
		}
	}
	$max_db_id+=100000;
 
	//开始为输出的对象添加内容,我们可以通过参数列表的classes参数定义特殊样式,也可以自定义target、description等输出内容作为特殊使用,以下列表应该已经列出了所有可能用得到的菜单输出项
	$new_items = array();
	$current_order = count($items) + 1;
	foreach ($brand_posts as $post) {
		$max_db_id++;//确保ID唯一
 
		//创建新的菜单项对象
		$new_item = new stdClass();
		$new_item->ID = $max_db_id;
		$new_item->db_id = $max_db_id;
		$new_item->title = $post->post_title;
		$new_item->url = get_permalink($post->ID);
		$new_item->menu_order = $current_order++;
		$new_item->menu_item_parent = $parent_item->ID;
		$new_item->type = 'post_type';
		$new_item->object = 'brand';
		$new_item->object_id = $post->ID;
		$new_item->classes = array('menu-brand-'.$post->ID, 'menu-brand-item');
		$new_item->target = '';
		$new_item->attr_title = '';
		$new_item->description = '';
		$new_item->xfn = '';
		$new_item->status = 'publish';
		$new_item->post_type = 'nav_menu_item';
		$new_item->post_status = 'publish';
		$new_item->post_name = 'brand-' . $post->post_name;
		$new_item->current = false;
		$new_item->current_item_ancestor = false;
		$new_item->current_item_parent = false;
		$new_items[] = $new_item;
	}
 
	//将新增加的菜单项插入到已指定的父菜单项之后
	$final_items = array();
	foreach ($items as $item) {
		$final_items[] = $item;
		if ($item->ID == $parent_item->ID) {
			//在父菜单项后插入所有子菜单项
			foreach ($new_items as $new_item) {
				$final_items[] = $new_item;
			}
		}
	}
 
	return $final_items;
}
add_filter('wp_nav_menu_objects', 'brain1981_add_posts_to_menu', 10, 2);

全文完。

本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/3456.html。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

关注我们的微信公众号-JennyStudio 本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注