Skip to content

Tout pour WordPress, le développement web — et plus encore

🚀 Comment se connecter à Contact Form 7 avant l'envoi du formulaire

🚀 Comment se connecter à Contact Form 7 avant l'envoi du formulaire

Contact Form 7 est installé sur des millions de sites WordPress. Il est simple, fiable et gratuit. Mais dès que le comportement standard ne suffit plus et que vous devez valider un champ, définir un destinataire dynamique ou annuler un email selon une condition, vous entrez dans le territoire du «comment est-ce qu’on fait ça, au juste».

La documentation de CF7 décrit brièvement les hooks. Les forums et Stack Overflow sont jonchés d’extraits pour d’anciennes versions du plugin, et un code vieux de cinq ans casse silencieusement sur un CF7 moderne. Voyons quels hooks sont réellement d’actualité aujourd’hui et comment s’y brancher sans mauvaise surprise.

💡 Aperçu rapide:

  • le hook principal est wpcf7_before_send_mail, le point d’entrée pour toute logique de pré-envoi.
  • vous pouvez sauter l’envoi de l’email avec le filtre wpcf7_skip_mail ou une simple ligne skip_mail: on dans les paramètres du formulaire.
  • pour obtenir les données soumises, utilisez l’objet $submission et la méthode get_posted_data().
  • pour changer le destinataire dynamiquement, utilisez set_properties() sur l’objet formulaire.
  • pour la validation de champ, utilisez wpcf7_validate avec un filtre par type de champ.

Pourquoi vous avez besoin des hooks de pré-envoi

Le scénario CF7 standard ressemble à ceci: un utilisateur remplit les champs, clique sur «Envoyer», le plugin envoie un email à une adresse fixe. C’est tout. Ajouter de la logique dans ce processus sans hooks est impossible.

Le hook wpcf7_before_send_mail et les filtres associés vous permettent d’intervenir dans la chaîne exactement au moment où les données ont été validées mais où l’email n’a pas encore été envoyé. Vous pouvez:

  • vérifier une condition personnalisée et annuler la soumission;
  • enregistrer les données du formulaire dans une base de données ou une API externe;
  • changer le destinataire de l’email à la volée;
  • modifier le contenu de l’email;
  • déclencher une intégration avec un CRM ou un service d’envoi d’emails.

Tous les exemples ci-dessous fonctionnent avec Contact Form 7 version 5.2 et supérieure. Si votre plugin est plus ancien, mettez-le à jour d’abord: les anciennes signatures de hooks sont incompatibles.

Wpcf7_before_send_mail, le point d’entrée

À partir de la version 5.2, la signature du hook a changé. Auparavant, seul l’objet formulaire était passé; désormais, il y a trois arguments:

1add_filter( 'wpcf7_before_send_mail', 'cf7_before_send_handler', 10, 3 );
2
3function cf7_before_send_handler( $contact_form, $abort, $submission ) {
4 // $contact_form — WPCF7_ContactForm object
5 // $abort — abort flag (true/false)
6 // $submission — WPCF7_Submission object with data
7
8 // your logic here
9
10 return $contact_form;
11}

Fichier de placement: functions.php de votre thème actif ou le plugin Code Snippets. La priorité 10 convient à la plupart des tâches; augmentez-la à 1 si votre callback doit s’exécuter avant les autres, ou descendez-la à 99 s’il doit s’exécuter après.

Notez que ce hook est un filtre, pas une action. Vous devez retourner l’objet $contact_form (ou WPCF7_ContactForm), sinon la chaîne se brisera de manière incorrecte.

Sauter l’envoi de l’email

Le cas d’usage le plus courant: ne pas envoyer de notification si un champ est rempli d’une manière spécifique. Il y a deux approches.

Utiliser le filtre wpcf7_skip_mail

Court et propre. Le filtre accepte une valeur booléenne et l’objet formulaire:

1add_filter( 'wpcf7_skip_mail', 'maybe_skip_mail', 10, 2 );
2
3function maybe_skip_mail( $skip_mail, $contact_form ) {
4 $submission = WPCF7_Submission::get_instance();
5
6 if ( $submission ) {
7 $data = $submission->get_posted_data();
8
9 // do not send email if field your-reason equals 'test'
10 if ( 'test' === ( $data['your-reason'] ?? '' ) ) {
11 $skip_mail = true;
12 }
13 }
14
15 return $skip_mail;
16}

La méthode WPCF7_Submission::get_instance() donne accès aux données de soumission dans ce filtre. Sans elle, get_posted_data() est indisponible puisque $submission n’est pas passé directement à wpcf7_skip_mail.

Utiliser les paramètres additionnels

Si la logique est aussi simple que possible (toujours sauter l’email pour un formulaire spécifique), allez dans le panneau d’administration. Dans l’onglet «Paramètres additionnels» du formulaire, ajoutez une ligne:

1skip_mail: on

Aucun code requis. Le plugin arrête l’envoi de l’email juste après la validation, et l’utilisateur voit un message de succès. Parfait pour les formulaires de démonstration et les environnements de test.

Une alternative avec le même effet: demo_mode: on. La différence est que demo_mode simule entièrement le succès sans toucher au sous-système d’envoi, tandis que skip_mail saute seulement l’étape d’envoi, en préservant tout le reste du comportement.

Obtenir les données soumises

L’objet $submission (le troisième argument de wpcf7_before_send_mail) donne un accès complet à ce que l’utilisateur a soumis:

1add_filter( 'wpcf7_before_send_mail', 'cf7_read_form_data', 10, 3 );
2
3function cf7_read_form_data( $contact_form, $abort, $submission ) {
4 // all fields at once
5 $posted = $submission->get_posted_data();
6
7 // specific field (key — name attribute of the tag in the form)
8 $user_name = $submission->get_posted_data( 'your-name' );
9 $user_email = $submission->get_posted_data( 'your-email' );
10
11 // ID of the post from which the form was sent
12 $post_id = $submission->get_meta( 'container_post_id' );
13
14 // form ID
15 $form_id = $contact_form->id();
16
17 // save to log or external service
18 if ( $user_email ) {
19 // for example, add subscriber to mailing list
20 }
21
22 return $contact_form;
23}

Les clés de champ ('your-name', 'your-email') sont les valeurs de l’attribut name dans les shortcodes du formulaire. Les balises standard comme [text* your-name], [email* your-email] produisent des clés sans préfixe; recopiez simplement ce qui vient après l’espace.

Important: get_posted_data() retourne les données brutes avant traitement par les modèles d’email. Caractères spéciaux, sauts de ligne, tout est tel que l’utilisateur l’a saisi. Assainissez avant d’enregistrer en base de données avec sanitize_text_field() ou des fonctions similaires.

Changement dynamique de destinataire

Supposons que l’email doive partir vers différents gestionnaires selon le sujet sélectionné dans le formulaire. Nous changeons la propriété recipient à la volée:

1add_filter( 'wpcf7_before_send_mail', 'cf7_dynamic_recipient', 10, 3 );
2
3function cf7_dynamic_recipient( $contact_form, $abort, $submission ) {
4 $data = $submission->get_posted_data();
5 $department = $data['your-department'] ?? '';
6
7 $recipients = [
8 'sales' => '[email protected]',
9 'support' => '[email protected]',
10 'billing' => '[email protected]',
11 ];
12
13 if ( isset( $recipients[ $department ] ) ) {
14 $props = $contact_form->get_properties();
15 $props['mail']['recipient'] = $recipients[ $department ];
16 $contact_form->set_properties( $props );
17 }
18
19 return $contact_form;
20}

Les méthodes get_properties() et set_properties() travaillent avec le tableau des paramètres du formulaire, y compris la section mail. Vous pouvez changer non seulement le destinataire mais aussi le sujet (subject), le corps (body), les en-têtes additionnels (additional_headers) et l’expéditeur (sender).

Placez le code au même endroit: le functions.php de votre thème ou via Code Snippets. Testez sur un environnement de staging avant de déployer en production: une faute de frappe dans la clé du tableau mail sera ignorée silencieusement, et l’email partira à l’adresse par défaut.

Validation de champ avant envoi

CF7 fournit le filtre wpcf7_validate, qui se déclenche avant wpcf7_before_send_mail. Il reçoit un objet WPCF7_Validation et vous permet d’ajouter une erreur; le formulaire ne sera pas soumis tant que l’utilisateur ne l’aura pas corrigée:

1add_filter( 'wpcf7_validate_text*', 'cf7_custom_text_validation', 10, 2 );
2add_filter( 'wpcf7_validate_email*', 'cf7_custom_email_validation', 10, 2 );
3
4function cf7_custom_text_validation( $result, $tag ) {
5 $field_name = $tag->name;
6
7 if ( 'your-message' === $field_name ) {
8 $value = $_POST[ $field_name ] ?? '';
9
10 if ( mb_strlen( $value ) < 20 ) {
11 $result->invalidate( $tag, 'Message must be at least 20 characters long.' );
12 }
13 }
14
15 return $result;
16}
17
18function cf7_custom_email_validation( $result, $tag ) {
19 $value = $_POST[ $tag->name ] ?? '';
20
21 if ( $value && ! str_contains( $value, '@' ) ) {
22 $result->invalidate( $tag, 'Enter a valid email.' );
23 }
24
25 return $result;
26}

Le filtre est nommé selon le motif wpcf7_validate_<field type>: text* pour les champs texte obligatoires, email* pour les email, textarea* pour les zones de texte. Sans l’astérisque, il s’applique aux champs optionnels. $tag est un objet contenant les paramètres du champ de formulaire, y compris name.

Les erreurs sont ajoutées avec la méthode invalidate($tag, 'error text'). Le texte est libre et s’affiche sous le champ du formulaire. Pour une soumission en AJAX (le comportement par défaut de CF7), le message apparaît sans rechargement de page.

⁉️🤔 Questions fréquentes

Quelle est la différence entre wpcf7_before_send_mail et wpcf7_mail_sent?

wpcf7_before_send_mail se déclenche avant l’envoi de l’email; vous pouvez annuler l’email, changer le destinataire ou modifier les données qu’il contient. wpcf7_mail_sent est une action qui se déclenche après l’envoi réussi. Utilisez-la pour la journalisation, le déclenchement de webhooks ou l’écriture en base de données quand l’email est garanti d’avoir été envoyé. Si vous devez interrompre le processus, seul before_send_mail fonctionnera.

Puis-je me brancher sans éditer functions.php?

Oui, via le plugin Code Snippets (gratuit, dans le dépôt WordPress). Il fournit une interface pour ajouter des extraits PHP sans toucher au thème. Les extraits peuvent être activés et désactivés individuellement, ce qui est pratique pour le débogage. Une alternative est WPCode (anciennement Insert Headers and Footers), également gratuit et avec contrôle de portée; vous pouvez lier un extrait à un formulaire spécifique via une logique conditionnelle.

Comment vérifier que le hook se déclenche bien?

La méthode la plus simple: error_log( 'HOOK FIRED' ) à l’intérieur de la fonction de callback et vérifier wp-content/debug.log avec WP_DEBUG activé. Pour un débogage rapide sans logs, remplacez temporairement return $contact_form par wp_die('Hook works'). Ne faites pas cela sur un site en production; uniquement sur un environnement local ou de staging.

Que faire si mon code cesse de fonctionner après une mise à jour de CF7?

D’abord, vérifiez la signature du hook. Dans la version 5.2, le nombre d’arguments de wpcf7_before_send_mail est passé de 1 à 3. Si votre callback est déclaré sans le paramètre $submission, ajoutez-le. Ensuite, vérifiez que votre fonction retourne bien l’objet $contact_form. Enfin, consultez le journal d’erreurs PHP; CF7 ignore silencieusement les erreurs fatales à l’intérieur des hooks, le formulaire se soumet normalement et vous ne voyez pas le problème.

Existe-t-il un moyen de s’abonner à plusieurs formulaires avec un seul hook?

Oui, wpcf7_before_send_mail se déclenche pour tous les formulaires. À l’intérieur du callback, filtrez par ID: $contact_form->id() retourne un nombre correspondant à l’ID du shortcode du formulaire (par exemple, [contact-form-7 id="42"]). Comparez-le avec les IDs souhaités et exécutez une logique différente via if ou switch.

Que mettre dans les fonctions du thème vs. extraire dans un plugin

Les hooks CF7 fonctionnent techniquement depuis n’importe où: functions.php, Code Snippets, MU-plugin. Mais il y a une répartition pratique qui vous épargnera des maux de tête lors des changements de thème ou des mises à jour.

Le code lié à la logique métier (changement de destinataire, intégration CRM, sauvegardes en base de données) doit aller dans un plugin séparé ou Code Snippets. La raison est simple: changer de thème ne doit pas casser le routage des emails clients. La validation de champ, qui est souvent liée à la mise en page et aux classes du thème, peut rester dans functions.php; elle perdra de toute façon son sens lors d’un changement de thème.

Les extraits de plus de 30 lignes doivent être formatés en MU-plugin (wp-content/mu-plugins/cf7-custom.php). Les MU-plugins ne peuvent pas être désactivés depuis le panneau d’administration, s’exécutent avant les plugins classiques et ne nécessitent pas d’activation; déposez simplement le fichier, et le code fonctionne.

Pour les cas complètement isolés (un formulaire, un site), utilisez functions.php plus un thème enfant. Moins de fichiers, moins de confusion.

Ces mêmes principes s’appliquent à tout autre plugin de formulaire, qu’il s’agisse de WPForms, Gravity Forms ou Fluent Forms. Chacun a ses propres hooks, mais l’approche architecturale «logique métier séparée, logique de présentation avec le thème» est universelle.

La vidéo propose un découpage étape par étape de la validation de champ CF7 personnalisée avec un exemple en direct dans le panneau d’administration WordPress. L’approche est compatible avec le filtre wpcf7_validate décrit ci-dessus, regardez-la donc comme un complément visuel au code de la section validation.