I have added a snippet to add a “Profile” link to my website navigation menu. My code:
add_filter( 'wp_nav_menu_items', 'my_nav_menu_profile_link');
function my_nav_menu_profile_link($menu) {
if (!is_user_logged_in()){
return $menu;
} else {
$user_data = bbp_get_user_profile_url( get_current_user_id() );
$profilelink = '<li><a href="'.$user_data.'&edit" >Profile</a></li>';
$menu = $menu . $profilelink;
return $menu;
}
}
This code correctly display profile link in my menu, but now I want to move this “profile” link as sub menu of another main menu.
My Menu structure is as follows:
Home | My Account | Categories
I would like to add “profile” link under “My Account”. Any suggestions to solve this problem?
1
I’ve created these two functions you may use to add custom items to a given menu item present in your menu (page, post, link…).
In your case, you can add these function to your functions.php and call them like this:
$menu_name="Your Menu Name";
$name_of_menu_item_to_append_to = 'My Account';
$id_of_menu_item_to_append_to = get_wp_object_id( $name_of_menu_item_to_append_to, 'nav_menu_item' );
$new_submenu_item = array(
'text' => 'Profile',
'url' => 'http://someurl.com'
);
add_subitems_to_menu(
$menu_name,
$id_of_menu_item_to_append_to,
array( $new_submenu_item )
);
add_subitems_to_menu()
/**
* Adds custom items to a navigation menu
* Partially based on:
* http://teleogistic.net/2013/02/dynamically-add-items-to-a-wp_nav_menu-list/
*
* @param string $menu_name The name or slug of the navigation menu
* @param int $parent_object_id The id of the post/page, which must be present
* in the menu, and to which we want to add subitems
* @param array $subitems The sub-items to be added to the menu, as an
* array( array( 'text' => 'foo', 'url' => '/bar') )
*/
public function add_subitems_to_menu( $menu_name, $parent_object_id, $subitems ) {
// Don't add anything in admin area. Otherwise WP will try to display the items in the
// Menu editor and it won't work fine and cause strange behaviour
if ( is_admin() ) {
return;
}
// Use wp_get_nav_menu_items filter, is used by Timber to get WP menu items
add_filter( 'wp_get_nav_menu_items', function( $items, $menu )
use( $menu_name, $parent_object_id, $subitems ) {
// If no menu found, just return the items without adding anything
if ( $menu->name != $menu_name && $menu->slug != $menu_name ) {
return $items;
}
// Find the menu item ID corresponding to the given post/page object ID
// If no post/page found, the subitems won't have any parent (will be on 1st level)
$parent_menu_item_id = 0;
foreach ( $items as $item ) {
if ( $parent_object_id == $item->object_id ) {
$parent_menu_item_id = $item->ID;
break;
}
}
$menu_order = count( $items ) + 1;
foreach ( $subitems as $subitem ) {
// Create objects containing all (and only) those properties from WP_Post
// used by WP to create a menu item
$items[] = (object) array(
'ID' => $menu_order + 1000000000, // ID that WP won't use
'title' => $subitem['text'],
'url' => $subitem['url'],
'menu_item_parent' => $parent_menu_item_id,
'menu_order' => $menu_order,
// These are not necessary, but PHP warning will be thrown if undefined
'type' => '',
'object' => '',
'object_id' => '',
'db_id' => '',
'classes' => '',
);
$menu_order++;
}
return $items;
}, 10, 2);
}
get_wp_object_id()
/**
* Returns the WordPress ID of any post type or page by its title or name
* In the case you provide an ID it will "validate" it looking for any post with that ID
*
* @param mixed $post_identifier The title, name or ID of the post/page
* @param string $post_type The post type to look for (default: page)
*
* @return int The ID of the post/page if any, or 0
*/
public function get_wp_object_id( $post_identifier, $post_type="page" ) {
$post_id = 0;
if ( get_page_by_title( $post_identifier, OBJECT, $post_type ) ) {
$post_id = get_page_by_title( $post_identifier, OBJECT, $post_type )->ID;
}
else if ( get_page_by_path( $post_identifier, OBJECT, $post_type ) ) {
$post_id = get_page_by_path( $post_identifier, OBJECT, $post_type )->ID;
}
else if ( get_post( $post_identifier ) ) {
$post_id = get_post( $post_identifier )->ID;
}
return $post_id;
}