假设我有一个输出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菜单是带有自定义分类nav_menu_item
的帖子类型nav_menu
,我可以使用wp_insert_post
导入我的菜单,还是有一些复杂的方法(比如我需要为每个菜单设置对象术语?
我只需要一些关于如何以正确方式插入菜单的指示。
部分解决方案
所以我发现this链接,我接近实现我的需要。我这样做了
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 );
}
}
编辑:最后一段代码会将我的菜单设置为其中一个位置(我认为这不是正确的位置)。 $menu_location
数组只是位置名称slug作为键,名称作为值(它们在主题中定义,因此它们存在)。
此代码创建菜单,并将第一个分配给一个位置,但不链接任何页面。
EDIT2:我对foreach进行了一些编辑,包括实际工作的菜单位置。但有一些事情是行不通的。我无法在菜单上显示网址,菜单层次结构不起作用(parent->子关系)。
困扰我的是阵列$menu_data
。我把所有这些我不确定甚至有效的钥匙都放了。例如url
和parent-id
。所有developer page说的是它是一个菜单项数据的数组(好duuuh)。如果我能看到我需要的钥匙并放在里面会很有用......
EDIT3:所以我摆脱了我的错误(类需要是一个由空格分隔的字符串),但我不确定为什么我的层次结构不起作用,为什么我不喜欢得到一个网址字段。我需要更详细地浏览nav-menus.php
,看看我错过了什么。
EDIT4:好的,所以它几乎可以正常工作!出于某种原因,我收到了通知:
注意:尝试在第404行的C:\ xampp \ htdocs \ test \ wp-includes \ nav-menu.php中获取非对象的属性
注意:尝试在第405行的C:\ xampp \ htdocs \ test \ wp-includes \ nav-menu.php中获取非对象的属性
注意:尝试在第712行的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,除非他们是完成它。所以我被困在这里...
答案 0 :(得分:0)
好的,所以我解决了这个问题,经过大量的讨论。
<?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 );
}
}
所以要解释一下。
首先,您需要获取菜单位置(可以从主题模型中获得,您也可以将其放入数组中),然后创建菜单。即使从现有名称创建菜单,也会创建一个带有新ID的全新菜单。更重要的是,菜单项也会有新的ID。这让事情变得复杂了。
之后,您将列出现有项目,并在foreach循环中逐个开始更新新项目。但是你还需要有一种关系表,它将在旧网址和新网址之间建立关系。这非常重要,因为您之前导出的帖子与新地点的网址不同。
但是如果你拥有它,那么你只需要拉出这些关系,并在菜单项中放置新的url。此外,如果您的菜单项是一个页面,那么您需要将其ID放在menu-item-object-id
所在的位置。这非常重要,因为如果你不这样做,你会收到关于无法从wordpress nav-menu.php获取非对象属性的通知。这是url_to_postid()函数派上用场的地方。只需将你的网址放在那里,你就可以获得帖子的ID,或者如果它没有得到0。
现在您已经建立了菜单,并且您很高兴。可是等等!层次结构怎么样?
您在新菜单中添加的是菜单之间的旧关系。使用旧ID。这显然不会起作用,因为当你更新菜单项时,你会得到新的ID。因此,您需要一个新的关系表,它将旧的ID与新ID相关联,您还需要一种方法来查看哪些菜单项中包含parent-id
个,这样你就可以重新获取所有信息。
问题是,您已经创建了菜单,因此您需要再次检查这些关系,并替换它们,最好的办法就是看看哪些菜单有这样的关系,只更新那些菜单(这就是你有2 wp_update_nav_menu_item()
个电话的原因。
之后你可以更新导航菜单对象(虽然我不确定这是否真的需要,但我看不出错误,为什么不呢),并将菜单设置到正确的位置。
我只需要检查多个子菜单和一些细节。但是现在这有效:)