vendredi 25 septembre 2026

À propos

Contact

Tips

Dupliquer un menu de navigation complet entre deux emplacements en un clic

Reconstruire un menu à la main pour un second emplacement fait perdre du temps et introduit des erreurs. Une action de duplication programmatique règle le problème.

Par Clément Hadrot • 8 août 2024 • 5 min de lecture • Aucun commentaire
Dupliquer un menu de navigation complet entre deux emplacements en un clic

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

L'essentiel à retenir : wp_get_nav_menu_items pour lire la structure source ; wp_update_nav_menu_item pour recréer chaque entrée ; Conserver la hiérarchie parent-enfant lors de la copie

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 taxonomy ou post_type dont l’objet source pourrait avoir été supprimé entre-temps : toujours vérifier object_id avant 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.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi