假设我有一个通过输出wp_get_nav_menus()
(和一些修改)得到的数组,我想将它导入到新安装的wordpress中。数组看起来像这样(我们称之为$menu_array
):
Array
(
[0] => Array
(
[term_id] => 5
[name] => my second menu
[slug] => my-second-menu
[term_group] => 0
[term_taxonomy_id] => 5
[taxonomy] => nav_menu
[description] =>
[parent] => 0
[count] => 2
[items] => Array
(
[0] => Array
(
[ID] => 14
[post_author] => 1
[post_date] => 2015-10-06 07:32:03
[post_date_gmt] => 2015-10-06 07:32:03
[post_content] =>
[post_title] => This is my menu
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => this-is-my-menu
[to_ping] =>
[pinged] =>
[post_modified] => 2015-10-12 10:31:23
[post_modified_gmt] => 2015-10-12 10:31:23
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://www.example.com/?p=14
[menu_order] => 1
[post_type] => nav_menu_item
[post_mime_type] =>
[comment_count] => 0
[filter] => raw
[db_id] => 14
[menu_item_parent] => 0
[object_id] => 14
[object] => custom
[type] => custom
[type_label] => Custom Link
[title] => This is my menu
[url] => #
[target] =>
[attr_title] =>
[description] =>
[classes] => Array
(
[0] =>
)
[xfn] =>
)
[1] => Array
(
[ID] => 15
[post_author] => 1
[post_date] => 2015-10-06 07:32:03
[post_date_gmt] => 2015-10-06 07:32:03
[post_content] =>
[post_title] => second menu
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => second-menu
[to_ping] =>
[pinged] =>
[post_modified] => 2015-10-12 10:31:23
[post_modified_gmt] => 2015-10-12 10:31:23
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://www.example.com/?p=15
[menu_order] => 2
[post_type] => nav_menu_item
[post_mime_type] =>
[comment_count] => 0
[filter] => raw
[db_id] => 15
[menu_item_parent] => 0
[object_id] => 15
[object] => custom
[type] => custom
[type_label] => Custom Link
[title] => second menu
[url] => #
[target] =>
[attr_title] =>
[description] =>
[classes] => Array
(
[0] =>
)
[xfn] =>
)
)
)
[1] => Array
(
[term_id] => 2
[name] => My Menu
[slug] => my-menu
[term_group] => 0
[term_taxonomy_id] => 2
[taxonomy] => nav_menu
[description] =>
[parent] => 0
[count] => 3
[items] => Array
(
[0] => Array
(
[ID] => 1104
[post_author] => 1
[post_date] => 2015-10-19 13:31:48
[post_date_gmt] => 2015-10-19 13:31:48
[post_content] =>
[post_title] =>
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => 1104
[to_ping] =>
[pinged] =>
[post_modified] => 2015-10-19 13:31:48
[post_modified_gmt] => 2015-10-19 13:31:48
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://www.example.com/?p=1104
[menu_order] => 1
[post_type] => nav_menu_item
[post_mime_type] =>
[comment_count] => 0
[filter] => raw
[db_id] => 1104
[menu_item_parent] => 0
[object_id] => 1016
[object] => page
[type] => post_type
[type_label] => Page
[url] => http://www.example.com/Test-page
[title] => Test page
[target] =>
[attr_title] =>
[description] =>
[classes] => Array
(
[0] =>
)
[xfn] =>
)
[1] => Array
(
[ID] => 12
[post_author] => 1
[post_date] => 2015-10-05 13:52:35
[post_date_gmt] => 2015-10-05 13:52:35
[post_content] =>
[post_title] => Google
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => google
[to_ping] =>
[pinged] =>
[post_modified] => 2015-10-19 13:31:48
[post_modified_gmt] => 2015-10-19 13:31:48
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://www.example.com/?p=12
[menu_order] => 2
[post_type] => nav_menu_item
[post_mime_type] =>
[comment_count] => 0
[filter] => raw
[db_id] => 12
[menu_item_parent] => 0
[object_id] => 12
[object] => custom
[type] => custom
[type_label] => Custom Link
[title] => Google
[url] => http://google.com
[target] =>
[attr_title] =>
[description] =>
[classes] => Array
(
[0] =>
)
[xfn] =>
)
[2] => Array
(
[ID] => 13
[post_author] => 1
[post_date] => 2015-10-06 07:22:39
[post_date_gmt] => 2015-10-06 07:22:39
[post_content] =>
[post_title] => Gmail
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => gmail
[to_ping] =>
[pinged] =>
[post_modified] => 2015-10-19 13:31:48
[post_modified_gmt] => 2015-10-19 13:31:48
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://www.example.com/?p=13
[menu_order] => 3
[post_type] => nav_menu_item
[post_mime_type] =>
[comment_count] => 0
[filter] => raw
[db_id] => 13
[menu_item_parent] => 12
[object_id] => 13
[object] => custom
[type] => custom
[type_label] => Custom Link
[title] => Gmail
[url] => #
[target] =>
[attr_title] =>
[description] =>
[classes] => Array
(
[0] =>
)
[xfn] =>
)
)
)
)
这是一个名为"我的菜单"的菜单,它有2个页面,我可以为多个菜单创建多个数组,层次结构遵循菜单。
我看了一下wordpress如何处理导入它,它使用wp_update_nav_menu_item()
和wp_nav_menu_update_menu_items()
。
我试过了,但到目前为止,我没有任何运气。
但是因为wordpress菜单是post类型nav_menu_item
自定义分类法nav_menu
,我可以使用wp_insert_post
来导入我的菜单,或者有一些复杂的方法来做到这一点(比如我需要为每个菜单设置对象术语)?
我只是需要一些关于如何以正确的方式插入菜单的指导。
部分解决方案
所以我找到了这个链接,我接近实现我需要的。我是这样做的
foreach ($menu_array as $menu => $menu_val) {
// Check if the menu exists
$old_menu_id = $menu_val['term_id'];
$menu_location = '';
foreach (get_theme_mod('nav_menu_locations') as $old_menu_loc => $loc_id) {
if ($old_menu_id == $loc_id) {
$menu_location .= $old_menu_loc;
}
}
$menu_name = $menu_val['name'];
$menu_exists = wp_get_nav_menu_object( $menu_name );
// If it doesn't exist, let's create it.
if( !$menu_exists){
$menu_id = wp_create_nav_menu($menu_name);
$old_object_id = array();
// Set up default menu items
foreach ($menu_val['items'] as $item => $item_value) {
$old_url = $item_value['url'];
$old_object_id[] .= $item_value['object_id'];
$new_url = (isset($url_relation_table[$old_url]) && $url_relation_table[$old_url]>0) ? $url_relation_table[$old_url] : $old_url;
$menu_data = array(
'menu-item-db-id' => 0,
'menu-item-object-id' => '',
'menu-item-object' => $item_value['object'],
'menu-item-parent-id' => 0,
'menu-item-position' => $item_value['menu_order'],
'menu-item-title' => $item_value['title'],
'menu-item-type' => $item_value['type'], //when removed no error but also no menu type!
'menu-item-url' => ($new_url != '') ? $new_url : '#',
'menu-item-description' => $item_value['description'],
'menu-item-attr-title' => $item_value['attr_title'],
'menu-item-target' => $item_value['target'],
'menu-item-classes' => implode(' ', $item_value['classes']),
'menu-item-xfn' => $item_value['xfn'],
'menu-item-status' => $item_value['post_status'],
);
wp_update_nav_menu_item($menu_id, 0, $menu_data);
}
$new_menu_item = wp_get_nav_menu_items($menu_id);
$new_object_id = array();
foreach ($new_menu_item as $new_item => $new_item_value) {
$new_object_id[] .= $new_item_value->ID;
}
$object_id_relation_array = array_combine($old_object_id, $new_object_id);
$menu_obj_data = array(
'description' => $menu_val['description'],
'menu-name' => $menu_val['name'],
'parent' => $menu_val['parent'],
);
wp_update_nav_menu_object($menu_id, $menu_obj_data);
}
$locations = array();
if ($menu_location != '') {
$locations[$menu_location] = $menu_id;
set_theme_mod( 'nav_menu_locations', $locations );
}
}
EDIT:这最后一段代码将把我的菜单设置为其中一个位置(我不认为这是正确的)。$menu_location
数组只是位置名称作为键和名称作为值(它们在主题中定义,因此它们存在)。
此代码创建菜单,并将第一个菜单分配给一个位置,但没有链接页面。
EDIT2:我已经编辑了foreach一点,包括实际工作的菜单位置。但有些事情行不通。我无法让url显示在我的菜单上,并且菜单层次结构不起作用(父->子关系)。
困扰我的是数组$menu_data
。我把这些我都不确定是否有效的钥匙。例如url
和parent-id
。所有的开发人员页面说,它是一个数组的菜单项的数据(好吧,duduuh)。如果我能知道我需要什么钥匙,可以放在里面,那就太好了。
EDIT3:所以我摆脱了我的错误(类需要是一个由空格分隔的字符串),但我不知道为什么我的层次结构不起作用,以及为什么我没有得到url字段。我需要更详细地浏览nav-menus.php
,看看我错过了什么。
EDIT4:好吧,所以它几乎工作!由于某些原因,我收到通知:
注意:试图获得非对象的属性在C:'xampp'htdocs'test'wp-includes'nav-menu.php行404
注意:试图在C:'xampp'htdocs'test'wp-includes'nav-menu.php中获得非对象的属性
注意:试图在C:'xampp'htdocs'test'wp-includes'nav-menu.php中获得非对象的属性
当我删除$item_value['type']
一切工作,但我没有得到我的菜单的帖子类型,所以都是自定义的,没有链接,所以简而言之,它不工作xD
另一件真正困扰我的事情是,我不能让层次结构工作。因此,当我导入菜单时,我将得到menu_item_parent
是菜单项对象的ID(如果是的话)。在我的例子中,最后一个具有object id
13的菜单是具有object id
12的菜单项的子菜单,所以他的menu_item_parent
是12。在创建新菜单时,情况会发生变化。因此,我创建了一个关系表,将旧菜单id与新菜单id联系起来。但我一直纠结于如何更新它。当我再次尝试更新菜单时,我把所有东西都搞砸了。我设法取代url(我有url关系表,其中有旧的和新的url),这是有效的,但由于菜单项是从无到有创建的,我不能只是去检查他们现在有什么id,除非他们完成了它。
好了,经过一番折腾,我解决了这个问题。
<?php
foreach ($menu_array as $menu => $menu_val) {
// Check if the menu exists
$old_menu_id = $menu_val['term_id'];
$menu_location = '';
foreach (get_theme_mod('nav_menu_locations') as $old_menu_loc => $loc_id) {
if ($old_menu_id == $loc_id) {
$menu_location .= $old_menu_loc;
}
}
$menu_name = $menu_val['name'];
$menu_exists = wp_get_nav_menu_object( $menu_name );
// If it doesn't exist, let's create it.
if( !$menu_exists){
$menu_id = wp_create_nav_menu($menu_name);
$old_object_id = array();
//Set up default menu items
foreach ($menu_val['items'] as $item => $item_value) {
$old_url = $item_value['url'];
$old_object_id[] .= $item_value['object_id'];
$new_url = (isset($url_relation_table[$old_url])) ? $url_relation_table[$old_url] : $old_url;
$obj_ID = url_to_postid($new_url);
$menu_data = array(
'menu-item-db-id' => '',
'menu-item-object-id' => ( $obj_ID != 0 ) ? $obj_ID : '',
'menu-item-object' => $item_value['object'],
'menu-item-parent-id' => $item_value['menu_item_parent'],
'menu-item-position' => $item_value['menu_order'],
'menu-item-title' => $item_value['title'],
'menu-item-type' => $item_value['type'],
'menu-item-url' => ($new_url != '') ? $new_url : '#',
'menu-item-description' => $item_value['description'],
'menu-item-attr-title' => $item_value['attr_title'],
'menu-item-target' => $item_value['target'],
'menu-item-classes' => implode(' ', $item_value['classes']),
'menu-item-xfn' => $item_value['xfn'],
'menu-item-status' => $item_value['post_status'],
);
wp_update_nav_menu_item($menu_id, 0, $menu_data);
}
$new_menu_item = wp_get_nav_menu_items($menu_id);
$new_object_id = array();
$parent_id = array();
foreach ($new_menu_item as $new_item => $new_item_value) {
$new_object_id[] .= $new_item_value->ID;
$parent_id[] .= $new_item_value->menu_item_parent;
}
$object_id_relation_array = array_combine($old_object_id, $new_object_id);
$parent_relation_array = array_combine($new_object_id, $parent_id);
foreach ($object_id_relation_array as $object_id_relation_key => $object_id_relation_value) {
foreach ($parent_id as $parent_id_key => $parent_id_value) {
if ($object_id_relation_key == $parent_id_value) {
$new_parent_id = $object_id_relation_value;
$item_id = array_search($parent_id_value, $parent_relation_array);
foreach ($new_menu_item as $single_item => $single_item_value) {
if ($single_item_value->ID == $item_id) {
$object = $single_item_value->object;
$object_ID = $single_item_value->object_id;
$position = $single_item_value->menu_order;
$title = $single_item_value->title;
$type = $single_item_value->type;
$url = $single_item_value->url;
$description = $single_item_value->description;
$attr_title = $single_item_value->attr_title;
$target = $single_item_value->target;
$classes = implode(' ', $single_item_value->classes);
$xfn = $single_item_value->xfn;
$status = $single_item_value->post_status;
$update_parent_id = array(
'menu-item-db-id' => $item_id,
'menu-item-object-id' => $object_ID,
'menu-item-object' => $object,
'menu-item-parent-id' => $new_parent_id,
'menu-item-position' => $position ,
'menu-item-title' => $title ,
'menu-item-type' => $type ,
'menu-item-url' => $url ,
'menu-item-description' => $description ,
'menu-item-attr-title' => $attr_title ,
'menu-item-target' => $target ,
'menu-item-classes' => $classes ,
'menu-item-xfn' => $xfn ,
'menu-item-status' => $status ,
);
wp_update_nav_menu_item($menu_id, $item_id, $update_parent_id);
}
}
}
}
}
$menu_obj_data = array(
'description' => $menu_val['description'],
'menu-name' => $menu_val['name'],
'parent' => $menu_val['parent'],
);
wp_update_nav_menu_object($menu_id, $menu_obj_data);
}
$locations = array();
if ($menu_location != '') {
$locations[$menu_location] = $menu_id;
set_theme_mod( 'nav_menu_locations', $locations );
}
}
我来解释一下。
首先你需要获得菜单位置(可以从主题mod中获得,也可以放入数组中),然后你创建一个菜单。创建一个菜单,即使从已有的名称将创建一个全新的菜单与新的ID。更重要的是,菜单项也将有新的ID。这就有点复杂了。
之后,列出现有的项,并开始在foreach循环中逐个更新新项。但你还需要某种关系表来保存旧url和新url之间的关系。这是非常重要的,因为你以前导出的帖子没有和新地方相同的url。
但是如果你有它,那么你只需要拉出这些关系,并在一个菜单项中放置新的url。此外,如果你的菜单项是一个页面,那么你需要把它的ID, menu-item-object-id
是。这很重要,因为如果你不这样做,你会得到一个提示不能从wordpress nav-menu。php中获取非对象的属性。这就是url_to_postid()函数派上用场的地方。把你的url放在那里,你会得到文章的id,否则你会得到0。
现在你已经建立了你的菜单,你很高兴。但是等等!那么等级制度呢?
您在新菜单中放入的是菜单之间的旧关系。用旧身份证。这显然行不通,因为当你更新菜单项时,你会得到新的ID。因此,您需要一个新的关系表来连接旧ID和新ID,并且您还需要一种方法来查看哪些菜单项中有这些parent-id
,以便您可以重新提取所有信息。
问题是,你已经创建了你的菜单,所以你需要再次检查这些关系,并替换它们,最好的事情就是看看哪些菜单有这样的关系,并且只更新那些菜单(这就是为什么你有2个wp_update_nav_menu_item()
调用)。
之后,你可以更新导航菜单对象(虽然我不确定这是不是真的需要,但我没有看到错误,所以为什么不呢),并设置菜单到正确的位置。
我只需要检查多个子菜单和一些细节。但现在这工作:)