# Router un formulaire de contact vers le bon artisan selon le métier visé

> Un collectif d'artisans partage un seul site et un seul formulaire. Voici comment aiguiller chaque demande vers le bon corps de métier sans plugin de routage lourd.

- Auteur : WordPress Développement
- Publié le : 2023-01-15
- Mis à jour le : 2023-01-15
- Catégorie : Extensions
- URL : https://www.wpmoderne.fr/extensions/artisan-router-formulaire-contact-metier/

## L’essentiel

- Une table de correspondance stockée en option
- admin-post.php plutôt qu'un plugin de formulaires complet
- Copie systématique à un artisan de secours

Comment un formulaire de contact unique peut-il atterrir dans la boîte mail du bon artisan, sans installer un plugin de routage complet pour six corps de métier différents ? C'est la question posée par un collectif d'artisans qui partagent un site vitrine commun : menuisier, électricien, plombier, carreleur, peintre et couvreur figurent tous sur la même page « Contact », avec un unique champ de sélection.

La réponse tient en une trentaine de lignes de code, à condition de s'appuyer sur les bons points d'entrée de WordPress plutôt que d'installer une usine à gaz pensée pour des formulaires à embranchements complexes. Voici le problème, le code qui le résout, puis les variantes utiles selon le contexte.

## Le problème posé

Le formulaire de contact propose un champ `metier` (menuiserie, électricité, plomberie, etc.) et doit envoyer le message à l'adresse de l'artisan correspondant, avec une copie systématique à une adresse de secours en cas d'absence prolongée. Un plugin de formulaires généraliste sait faire du routage conditionnel, mais impose souvent une interface de règles disproportionnée pour six cas fixes et connus à l'avance.

## Le snippet commenté

> L'essentiel à retenir : Une table de correspondance stockée en option ; admin-post.php plutôt qu'un plugin de formulaires complet ; Copie systématique à un artisan de secours

La solution repose sur trois éléments standards de WordPress : un formulaire HTML classique posté vers `admin-post.php`, une action accrochée en `admin_post_nopriv_` pour les visiteurs non connectés, et une table de correspondance stockée en option, modifiable sans toucher au code :

```
// Table de correspondance, modifiable depuis l’administration
function artisans_table_routage() {
    return get_option( 'artisans_routage', array(
        'menuiserie'  => 'menuiserie@collectif-artisans.test',
        'electricite' => 'electricite@collectif-artisans.test',
        'plomberie'   => 'plomberie@collectif-artisans.test',
        'carrelage'   => 'carrelage@collectif-artisans.test',
        'peinture'    => 'peinture@collectif-artisans.test',
        'couverture'  => 'couverture@collectif-artisans.test',
    ) );
}

add_action( 'admin_post_nopriv_contact_artisan', 'artisans_traiter_contact' );
add_action( 'admin_post_contact_artisan', 'artisans_traiter_contact' );

function artisans_traiter_contact() {
    if ( ! isset( $_POST['artisans_nonce'] ) || ! wp_verify_nonce( $_POST['artisans_nonce'], 'contact_artisan' ) ) {
        wp_die( 'Requête invalide.' );
    }

    $metier   = sanitize_key( $_POST['metier'] ?? '' );
    $message  = sanitize_textarea_field( $_POST['message'] ?? '' );
    $email_de = sanitize_email( $_POST['email'] ?? '' );

    $table = artisans_table_routage();
    $vers  = $table[ $metier ] ?? 'contact@collectif-artisans.test';

    wp_mail(
        $vers,
        'Nouvelle demande de contact',
        $message . "\n\nRépondre directement à : " . $email_de,
        array( 'Cc: secours@collectif-artisans.test' )
    );

    wp_safe_redirect( home_url( '/merci' ) );
    exit;
}
```

Le champ `metier` transmis par le formulaire est validé avec `sanitize_key()`, ce qui élimine tout caractère indésirable avant de servir de clé au tableau de correspondance : une valeur absente de la table retombe automatiquement sur l'adresse générale, sans erreur PHP.

## Pourquoi admin-post.php plutôt qu'un endpoint REST

Pour un formulaire de contact classique, sans besoin d'interaction JavaScript asynchrone, `admin-post.php` reste le point d'entrée le plus simple : il gère nativement les utilisateurs connectés et non connectés via les deux préfixes d'action, sans avoir à déclarer de route REST ni à gérer de nonce d'API distinct. C'est un choix pragmatique, pas un choix par défaut : dès qu'un enrichissement JavaScript devient nécessaire (validation en temps réel, envoi sans rechargement), un contrôleur REST personnalisé reprend tout son sens.

## Variantes utiles

### Router selon plusieurs critères combinés

Si le collectif ajoute une notion de zone géographique en plus du métier, la table de correspondance devient un tableau à deux niveaux, indexé par `metier` puis par `zone`, avec un repli sur le métier seul si la zone n'est pas renseignée. Le principe de repli progressif reste identique : toujours prévoir une valeur par défaut plutôt qu'un email non trouvé.

### Journaliser les demandes sans base de données dédiée

Pour garder une trace des demandes envoyées sans créer de table personnalisée, chaque envoi peut être enregistré comme un post du type `demande_contact` avec le métier en métadonnée, consultable depuis l'administration standard sans développement d'écran supplémentaire.

### Alerter en cas d'échec d'envoi

Comme `wp_mail()` ne renvoie qu'un booléen, il est utile d'accrocher le hook `wp_mail_failed`, qui reçoit un objet `WP_Error`, pour journaliser précisément la cause d'un échec d'envoi plutôt que de constater après coup qu'un artisan n'a jamais reçu ses demandes.

## En résumé

Pour un nombre de destinataires fixe et connu à l'avance, une table de correspondance en option et un traitement via `admin-post.php` couvrent le besoin sans complexité superflue. Le jour où le nombre de métiers ou de critères de routage explose, la bascule vers un contrôleur REST personnalisé ou un plugin de formulaires dédié redevient justifiée, mais elle n'est pas nécessaire pour six corps de métier stables.
