You can use wp_update_nav_menu_item()
to programmatically add a new menu item to the database. Since this change persists, you shouldn't execute this functionality on every page - it's best used as a one-off (though in that case it might be easier and more efficient to use WP CLI as suggested by WebElaine in the comments), or via some dashboard interaction if it's something you intend to use repeatedly.
/**
* Insert a new navigation menu item for a page into the database.
*
* @link https://wordpress.stackexchange.com/questions/408618
*
* @param int $menu_id The ID of the menu to insert the new item into.
* @param int|WP_Post|null $page A reference to the page for which to create a new menu item.
* @param string $title The title of the nav item. Defaults to the page title.
* @param int $parent The ID of the parent nav menu item, if applicable.
* @param int $position The index within the menu/parent for the new item. Defaults to 0 to append.
* @return int|WP_Error The ID of the new menu item on success, or a WP_Error object on failure.
**/
function wpse408618_insert_nav_menu_page_item(
$menu_id,
$page,
$title = null,
$parent = 0,
$position = 0
) {
$page = get_post( $page );
if( !$page || $page->post_type !== 'page' )
return new WP_Error( 'wpse408618_invalid_page_arg', 'The supplied $page argument could not be resolved to a page-type post.' );
$menu_item_data = array(
'menu-item-title' => isset( $title ) ? $title : get_the_title( $page ),
'menu-item-object-id' => $page->ID,
'menu-item-object' => 'page',
'menu-item-status' => 'publish',
'menu-item-type' => 'post-type',
'menu-item-parent-id' => $parent,
'menu-item-position' => $position,
);
return wp_update_nav_menu_item( $menu_id, 0, $menu_item_data );
}
$new_item_id = wpse408618_insert_nav_menu_page_item( 158, 15891 );
if( is_wp_error( $new_item_id ) )
echo 'Page nav menu item creation failed: "' . $new_item_id->get_error_message() . '"';
else
echo 'Page nav menu item creation succeeded! Item inserted with ID ' . $new_item_id;
You can refer to the source of the wp_update_nav_menu_item()
function for a more complete list of possible nav menu item object attributes.
It's also possible to use a hook such as the wp_get_nav_menu_items
filter to add non-persistent items on the fly, if it makes more sense for your application.