Une enseigne de literie avec plusieurs emplacements de menu (un menu principal, un menu pied de page partiellement identique, et un menu mobile qui devait reprendre exactement la même structure) demandait à son équipe marketing de recréer à la main, dans le pied de page, une bonne partie des entrées du menu principal chaque fois qu’une catégorie de produit était ajoutée. Le résultat : des oublis fréquents, et un pied de page qui prenait du retard sur le menu principal.
La solution consiste à ajouter, dans l’écran d’administration des menus, un bouton « Dupliquer vers » qui recopie programmatiquement toute la structure d’un menu existant vers un nouvel emplacement, hiérarchie comprise.
Lire la structure du menu source
La fonction wp_get_nav_menu_items() renvoie l’ensemble des éléments d’un menu, chacun sous forme d’objet contenant notamment son titre, son URL, son menu_item_parent (l’ID de l’élément parent, 0 pour un élément racine), et son ordre menu_order :
function literie_dupliquer_menu( int $id_menu_source, string $nom_menu_cible ) {
$elements = wp_get_nav_menu_items( $id_menu_source );
if ( ! $elements ) {
return new WP_Error( 'menu_vide', 'Le menu source est introuvable ou vide.' );
}
$menu_cible = wp_create_nav_menu( $nom_menu_cible );
if ( is_wp_error( $menu_cible ) ) {
return $menu_cible;
}
return literie_copier_elements( $elements, $menu_cible );
}
Recréer chaque élément en conservant la hiérarchie

Le point délicat de cette copie : un sous-menu référence son parent par l’ID de l’élément d’origine, qui n’existera évidemment plus dans le nouveau menu. Il faut donc garder une table de correspondance entre les anciens ID et les nouveaux, en traitant les éléments dans l’ordre où wp_get_nav_menu_items() les retourne (les parents avant leurs enfants, ce qui est déjà l’ordre naturel de cette fonction) :
function literie_copier_elements( array $elements, int $id_menu_cible ) {
$correspondance_ids = array();
foreach ( $elements as $element ) {
$nouveau_parent = 0;
if ( $element->menu_item_parent && isset( $correspondance_ids[ $element->menu_item_parent ] ) ) {
$nouveau_parent = $correspondance_ids[ $element->menu_item_parent ];
}
$nouvel_id = wp_update_nav_menu_item( $id_menu_cible, 0, array(
'menu-item-title' => $element->title,
'menu-item-url' => $element->url,
'menu-item-status' => 'publish',
'menu-item-parent-id' => $nouveau_parent,
'menu-item-position' => $element->menu_order,
'menu-item-type' => $element->type,
'menu-item-object' => $element->object,
'menu-item-object-id' => $element->object_id,
) );
if ( ! is_wp_error( $nouvel_id ) ) {
$correspondance_ids[ $element->ID ] = $nouvel_id;
}
}
return $id_menu_cible;
}
Le second argument 0 passé à wp_update_nav_menu_item() indique qu’il s’agit d’une création et non d’une mise à jour d’un élément existant : c’est ce paramètre qui déclenche la création d’un nouvel élément de menu plutôt que la modification d’un élément portant cet ID.
Affecter le nouveau menu à un emplacement
Une fois la copie terminée, il reste à associer ce nouveau menu à l’emplacement souhaité, via l’option theme_mods dédiée aux emplacements de menu :
function literie_assigner_a_emplacement( int $id_menu, string $emplacement ) {
$emplacements = get_theme_mod( 'nav_menu_locations', array() );
$emplacements[ $emplacement ] = $id_menu;
set_theme_mod( 'nav_menu_locations', $emplacements );
}
Ajouter le bouton dans l’écran d’administration
Pour rendre l’outil accessible sans passer par la console ou un script ponctuel, un simple lien d’action ajouté via le filtre nav_menu_options ou une action personnalisée déclenchée par un bouton dans l’écran nav-menus.php suffit à déclencher la fonction, avec une vérification de nonce classique :
add_action( 'admin_post_literie_dupliquer_menu', function () {
check_admin_referer( 'literie_dupliquer_menu' );
if ( ! current_user_can( 'edit_theme_options' ) ) {
wp_die( 'Action non autorisée.' );
}
$id_source = (int) ( $_POST['menu_source'] ?? 0 );
$resultat = literie_dupliquer_menu( $id_source, 'Pied de page (copie)' );
wp_safe_redirect( admin_url( 'nav-menus.php?message=dupliquee' ) );
exit;
} );
Ce qui casse souvent si on va trop vite
- Oublier de conserver l’ordre
menu_order: les éléments réapparaissent alors dans le désordre. - Copier les éléments avant leurs parents si la source a été manipulée manuellement (rare, mais possible après une modification directe en base).
- Ne pas gérer les éléments de type
taxonomyoupost_typedont l’objet source pourrait avoir été supprimé entre-temps : toujours vérifierobject_idavant la copie.
Sur un site à plusieurs emplacements de menu proches mais pas identiques, je préfère une duplication ponctuelle suivie d’ajustements manuels à une synchronisation permanente automatique : cette dernière finit presque toujours par bloquer une personnalisation légitime propre à un emplacement.
Pour aller plus loin
Cette même mécanique de copie avec table de correspondance d’ID s’applique à d’autres structures hiérarchiques de WordPress : taxonomies avec parents, pages avec pages enfants, ou blocs réutilisables imbriqués. Le principe reste identique : traiter les parents avant les enfants, et toujours garder la table de correspondance entre anciens et nouveaux identifiants pendant toute la durée de la copie.