Skip to content

Alt om WordPress, webutvikling — og mer til

🚀 Hvordan koble seg på Contact Form 7 før innsending av skjema

🚀 Hvordan koble seg på Contact Form 7 før innsending av skjema

Contact Form 7 er installert på millioner av WordPress-nettsteder. Det er enkelt, pålitelig og gratis. Men så snart standardoppførselen ikke strekker til og du trenger å validere et felt, sette en dynamisk mottaker eller avbryte en e-post basert på en betingelse, havner du i «hvordan i all verden gjør man dette»-terreng.

Dokumentasjonen for CF7 beskriver kroker kortfattet. Forum og Stack Overflow er fulle av kodebiter for gamle plugin-versjoner, og fem år gammel kode slutter å virke uten forvarsel på moderne CF7. La oss finne ut hvilke kroker som er aktuelle i dag, og hvordan du kan koble deg på dem uten overraskelser.

💡 Rask oversikt:

  • hovedkroken er wpcf7_before_send_mail, inngangsporten for all logikk før sending.
  • du kan hoppe over e-posten ved å bruke filteret wpcf7_skip_mail eller en enkelt linje skip_mail: on i skjemainnstillingene.
  • for å hente innsendte data, bruk $submission-objektet og metoden get_posted_data().
  • for å endre mottaker dynamisk, bruk set_properties() på skjemaobjektet.
  • for feltvalidering, bruk wpcf7_validate med et filter etter felttype.

Hvorfor du trenger kroker før sending

Standardscenarioet for CF7 ser slik ut: en bruker fyller ut felter, klikker «Send», og programtillegget sender en e-post til en fast adresse. Det er alt. Å legge til logikk i denne prosessen uten kroker er umulig.

Kroken wpcf7_before_send_mail og relaterte filtre lar deg gripe inn i kjeden nøyaktig i det øyeblikket dataene er validert, men e-posten ennå ikke er sendt. Du kan:

  • sjekke en egendefinert betingelse og avbryte innsendingen;
  • lagre skjemadata til en database eller et eksternt API;
  • endre e-postmottakeren i farten;
  • endre e-postinnholdet;
  • utløse en integrasjon med et CRM-system eller en utsendingstjeneste.

Alle eksemplene nedenfor fungerer med Contact Form 7 versjon 5.2 og nyere. Hvis programtillegget ditt er eldre, oppdater først: gamle kroksignaturer er inkompatible.

Wpcf7_before_send_mail, inngangsporten

Fra og med versjon 5.2 endret kroksignaturen seg. Tidligere ble bare skjemaobjektet sendt med; nå er det tre argumenter:

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}

Fil for plassering: functions.php i ditt aktive tema eller programtillegget Code Snippets. Prioritet 10 fungerer for de fleste oppgaver; øk den til 1 hvis tilbakekallet ditt må kjøre før andre, eller senk den til 99 hvis det skal kjøre etter.

Merk at denne kroken er et filter, ikke en handling. Du må returnere $contact_form-objektet (eller WPCF7_ContactForm), ellers vil kjeden brytes på feil måte.

Hoppe over e-postsending

Det vanligste bruksområdet: ikke send et varsel hvis et felt er fylt ut på en bestemt måte. Det finnes to tilnærminger.

Bruke wpcf7_skip_mail-filteret

Kort og ryddig. Filteret aksepterer en boolsk verdi og skjemaobjektet:

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}

Metoden WPCF7_Submission::get_instance() gir tilgang til innsendingsdata i dette filteret. Uten den er get_posted_data() utilgjengelig siden $submission ikke sendes direkte til wpcf7_skip_mail.

Bruke tilleggsinnstillinger

Hvis logikken er så enkel som mulig (alltid hopp over e-posten for et bestemt skjema), gå til administrasjonspanelet. I skjemaets fane «Tilleggsinnstillinger» legger du til én linje:

1skip_mail: on

Ingen kode nødvendig. Programtillegget stopper e-postsendingen rett etter validering, og brukeren ser en suksessmelding. Perfekt for demoskjemaer og testmiljøer.

Et alternativ med samme effekt: demo_mode: on. Forskjellen er at demo_mode fullstendig simulerer suksess uten å berøre e-postundersystemet, mens skip_mail bare hopper over sendetrinnet og bevarer all annen oppførsel.

Hente innsendte data

$submission-objektet (det tredje argumentet til wpcf7_before_send_mail) gir full tilgang til det brukeren sendte inn:

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}

Feltnøkler ('your-name', 'your-email') er verdiene til name-attributtet i skjemaets shortkoder. Standardtagger som [text* your-name], [email* your-email] produserer nøkler uten prefikser; bare kopier det som kommer etter mellomrommet.

Viktig: get_posted_data() returnerer rådata før behandling av e-postmaler. Spesialtegn, linjeskift, alt slik brukeren skrev det inn. Desinfiser før lagring i databasen ved å bruke sanitize_text_field() eller lignende funksjoner.

Dynamisk mottakerbytte

Anta at e-posten skal gå til forskjellige saksbehandlere avhengig av emnet som er valgt i skjemaet. Vi endrer egenskapen recipient i farten:

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}

Metodene get_properties() og set_properties() jobber med skjemaets innstillingsmatrise, inkludert mail-seksjonen. Du kan endre ikke bare mottakeren, men også emnet (subject), brødteksten (body), ekstra topptekster (additional_headers) og avsenderen (sender).

Plasser koden på samme sted: temaets functions.php eller via Code Snippets. Test på staging før du ruller ut til produksjon: en skrivefeil i mail-matrisenøkkelen vil bli ignorert uten lyd, og e-posten vil gå til standardadressen.

Feltvalidering før sending

CF7 tilbyr filteret wpcf7_validate, som utløses før wpcf7_before_send_mail. Det mottar et WPCF7_Validation-objekt og lar deg legge til en feil; skjemaet vil ikke bli sendt inn før brukeren retter den:

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}

Filteret navngis etter mønsteret wpcf7_validate_<field type>: text* for obligatoriske tekstfelt, email* for e-post, textarea* for tekstområder. Uten stjerne gjelder det for valgfrie felt. $tag er et objekt med skjemafeltparametere, inkludert name.

Feil legges til ved hjelp av metoden invalidate($tag, 'error text'). Teksten er vilkårlig og vises under skjemafeltet. For AJAX-innsending (standard i CF7) vises meldingen uten at siden lastes på nytt.

⁉️🤔 Ofte stilte spørsmål

Hva er forskjellen mellom wpcf7_before_send_mail og wpcf7_mail_sent?

wpcf7_before_send_mail utløses før e-posten sendes; du kan avbryte e-posten, endre mottakeren eller endre data i den. wpcf7_mail_sent er en handling som utløses etter vellykket sending. Bruk den til logging, utløsing av webhooks eller databaseskriving når e-posten garantert er sendt. Hvis du trenger å avbryte prosessen, er det bare before_send_mail som fungerer.

Kan jeg koble meg på uten å redigere functions.php?

Ja, via programtillegget Code Snippets (gratis, i WordPress-depotet). Det gir et grensesnitt for å legge til PHP-kodebiter uten å berøre temaet. Kodebiter kan aktiveres og deaktiveres individuelt, noe som er praktisk for feilsøking. Et alternativ er WPCode (tidligere Insert Headers and Footers), også gratis og med omfangskontroll; du kan binde en kodebit til et bestemt skjema gjennom betinget logikk.

Hvordan sjekker jeg at kroken faktisk utløses?

Den enkleste måten: error_log( 'HOOK FIRED' ) inne i tilbakekallet og sjekk wp-content/debug.log med WP_DEBUG aktivert. For rask feilsøking uten logger, erstatt midlertidig return $contact_form med wp_die('Hook works'). Ikke gjør dette på et produksjonsnettsted; bare på lokale miljøer eller staging-miljøer.

Hva bør jeg gjøre hvis koden min slutter å virke etter en CF7-oppdatering?

Først, sjekk kroksignaturen. I versjon 5.2 økte antall argumenter for wpcf7_before_send_mail fra 1 til 3. Hvis tilbakekallet ditt er deklarert uten $submission-parameteren, legg den til. For det andre, bekreft at funksjonen din returnerer $contact_form-objektet. For det tredje, sjekk PHP-feilloggen; CF7 ignorerer lydløst fatale feil inne i kroker, skjemaet sendes inn som vanlig, og du ser ikke problemet.

Finnes det en måte å abonnere på flere skjemaer med én krok?

Ja, wpcf7_before_send_mail utløses for alle skjemaer. Inne i tilbakekallet, filtrer etter ID: $contact_form->id() returnerer et tall som samsvarer med skjemaets shortkode-ID (for eksempel [contact-form-7 id="42"]). Sammenlign det med de nødvendige ID-ene og utfør forskjellig logikk via if eller switch.

Hva som bør legges i temafunksjoner vs. trekkes ut i et programtillegg

CF7-kroker fungerer teknisk sett fra hvor som helst: functions.php, Code Snippets, MU-plugin. Men det finnes en praktisk inndeling som vil spare deg for hodepine når du bytter tema eller oppdaterer.

Kode knyttet til forretningslogikk (mottakerbytte, CRM-integrasjon, databaselagring) bør legges i et separat programtillegg eller Code Snippets. Grunnen er enkel: bytte av tema bør ikke ødelegge klientens e-postruting. Feltvalidering, som ofte er knyttet til temaoppsett og klasser, kan forbli i functions.php; den vil uansett miste sin mening når temaet endres.

Kodebiter lengre enn 30 linjer bør formateres som et MU-plugin (wp-content/mu-plugins/cf7-custom.php). MU-plugins kan ikke deaktiveres fra administrasjonspanelet, kjøres før vanlige programtillegg og krever ikke aktivering; bare slipp filen inn, så fungerer koden.

For fullstendig isolerte tilfeller (ett skjema, ett nettsted), bruk functions.php pluss et child theme. Færre filer, mindre forvirring.

De samme prinsippene gjelder for ethvert annet skjemaprogramtillegg, enten det er WPForms, Gravity Forms eller Fluent Forms. Hver har sine egne kroker, men den arkitektoniske tilnærmingen «forretningslogikk separat, presentasjonslogikk med temaet» er universell.

Videoen gir en trinnvis gjennomgang av egendefinert CF7-feltvalidering med et levende eksempel i WordPress-administrasjonspanelet. Tilnærmingen er kompatibel med filteret wpcf7_validate beskrevet ovenfor, så se den som et visuelt supplement til koden fra valideringsseksjonen.