
🚀 Hur du kopplar in dig i Contact Form 7 före formulärinskick
Contact Form 7 är installerat på miljontals WordPress-sajter. Det är enkelt, pålitligt och gratis. Men så fort standardbeteendet inte räcker till och du behöver validera ett fält, sätta en dynamisk mottagare eller avbryta ett mejl baserat på ett villkor, hamnar du i "hur gör man ens detta"-träsket.
Dokumentationen för CF7 beskriver hooks kortfattat. Forum och Stack Overflow är fulla av kodsnuttar för gamla pluginversioner, och fem år gammal kod slutar fungera tyst på moderna CF7. Låt oss reda ut vilka hooks som är aktuella idag och hur du kopplar in dig i dem utan överraskningar.
💡 Snabb översikt:
- den huvudsakliga hooken är
wpcf7_before_send_mail, ingångspunkten för all logik före sändning. - du kan hoppa över mejlet med filtret
wpcf7_skip_maileller en enda radskip_mail: oni formulärinställningarna. - för att hämta inskickad data använder du objektet
$submissionoch metodenget_posted_data(). - för att ändra mottagaren dynamiskt använder du
set_properties()på formulärobjektet. - för fältvalidering använder du
wpcf7_validatemed ett filter per fälttyp.
Varför du behöver hooks före sändning
Standardscenariot för CF7 ser ut så här: en användare fyller i fält, klickar på "Skicka", och pluginet skickar ett mejl till en fast adress. Det är allt. Att lägga till logik i denna process utan hooks är omöjligt.
Hooken wpcf7_before_send_mail och relaterade filter låter dig ingripa i kedjan precis i det ögonblick då data har validerats men mejlet ännu inte har skickats. Du kan:
- kontrollera ett anpassat villkor och avbryta inskickningen;
- spara formulärdata till en databas eller externt API;
- ändra mejlmottagaren i farten;
- modifiera mejlinnehållet;
- utlösa en integration med ett CRM eller en e-posttjänst.
Alla exempel nedan fungerar med Contact Form 7 version 5.2 och senare. Om ditt plugin är äldre, uppdatera först: gamla hook-signaturer är inkompatibla.
Wpcf7_before_send_mail, ingångspunkten
Från och med version 5.2 ändrades hook-signaturen. Tidigare skickades bara formulärobjektet med; nu finns det tre argument:
1 add_filter( 'wpcf7_before_send_mail', 'cf7_before_send_handler', 10, 3 ); 2 3 function 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 för placering: functions.php i ditt aktiva tema eller tillägget Code Snippets. Prioriteten 10 fungerar för de flesta uppgifter; höj den till 1 om din callback behöver köras före andra, eller sänk den till 99 om den ska köras efter.
Observera att denna hook är ett filter, inte en action. Du måste returnera objektet $contact_form (eller WPCF7_ContactForm), annars bryts kedjan på fel sätt.
Hoppa över mejlsändning
Det vanligaste användningsfallet: skicka inte en notifiering om ett fält är ifyllt på ett specifikt sätt. Det finns två tillvägagångssätt.
Använda filtret wpcf7_skip_mail
Kort och rent. Filtret accepterar ett booleskt värde och formulärobjektet:
1 add_filter( 'wpcf7_skip_mail', 'maybe_skip_mail', 10, 2 ); 2 3 function 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() ger tillgång till inskickningsdata inom detta filter. Utan den är get_posted_data() otillgänglig eftersom $submission inte skickas direkt till wpcf7_skip_mail.
Använda ytterligare inställningar
Om logiken är så enkel som den kan bli (hoppa alltid över mejlet för ett specifikt formulär), gå till adminpanelen. På formulärets flik "Ytterligare inställningar" lägger du till en rad:
1 skip_mail: on
Ingen kod behövs. Pluginet stoppar mejlsändningen direkt efter validering, och användaren ser ett framgångsmeddelande. Perfekt för demoformulär och testmiljöer.
Ett alternativ med samma effekt: demo_mode: on. Skillnaden är att demo_mode fullständigt simulerar framgång utan att röra mejlundersystemet, medan skip_mail bara hoppar över sändningssteget och bevarar allt annat beteende.
Hämta inskickad data
Objektet $submission (det tredje argumentet till wpcf7_before_send_mail) ger full tillgång till vad användaren skickade in:
1 add_filter( 'wpcf7_before_send_mail', 'cf7_read_form_data', 10, 3 ); 2 3 function 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 }
Fältnycklar ('your-name', 'your-email') är värdena för attributet name i formulärets shortcodes. Standardtaggar som [text* your-name], [email* your-email] producerar nycklar utan prefix; kopiera bara det som kommer efter mellanslaget.
Viktigt: get_posted_data() returnerar rå data före bearbetning av mejlmallar. Specialtecken, radbrytningar, allt precis som användaren skrev in det. Sanera innan du sparar till databasen med sanitize_text_field() eller liknande funktioner.
Dynamiskt mottagarbyte
Anta att mejlet ska gå till olika handläggare beroende på vilket ämne som valts i formuläret. Vi ändrar egenskapen recipient i farten:
1 add_filter( 'wpcf7_before_send_mail', 'cf7_dynamic_recipient', 10, 3 ); 2 3 function 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 }
Metoderna get_properties() och set_properties() arbetar med formulärets inställningsarray, inklusive sektionen mail. Du kan ändra inte bara mottagaren utan även ämnet (subject), innehållet (body), ytterligare headers (additional_headers) och avsändaren (sender).
Placera koden på samma ställe: ditt temas functions.php eller via Code Snippets. Testa på staging innan du driftsätter i produktion: ett stavfel i arraynyckeln mail ignoreras tyst, och mejlet går till standardadressen.
Fältvalidering före sändning
CF7 tillhandahåller filtret wpcf7_validate, som körs före wpcf7_before_send_mail. Det tar emot ett WPCF7_Validation-objekt och låter dig lägga till ett fel; formuläret skickas inte förrän användaren åtgärdar det:
1 add_filter( 'wpcf7_validate_text*', 'cf7_custom_text_validation', 10, 2 ); 2 add_filter( 'wpcf7_validate_email*', 'cf7_custom_email_validation', 10, 2 ); 3 4 function 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 18 function 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 }
Filtret namnges enligt mönstret wpcf7_validate_<field type>: text* för obligatoriska textfält, email* för e-post, textarea* för textytor. Utan asterisken gäller det valfria fält. $tag är ett objekt med formulärfältsparametrar, inklusive name.
Fel läggs till med metoden invalidate($tag, 'error text'). Texten är godtycklig och visas under formulärfältet. Vid AJAX-inskickning (standard i CF7) visas meddelandet utan att sidan laddas om.
⁉️🤔 Vanliga frågor
Vad är skillnaden mellan wpcf7_before_send_mail och wpcf7_mail_sent?
wpcf7_before_send_mailkörs före mejlet skickas; du kan avbryta mejlet, ändra mottagaren eller modifiera data i det.wpcf7_mail_sentär en action som körs efter lyckad sändning. Använd den för loggning, triggning av webhooks eller databasskrivningar när mejlet garanterat har skickats. Om du behöver avbryta processen fungerar barabefore_send_mail.
Kan jag koppla in mig utan att redigera functions.php?
Ja, via tillägget Code Snippets (gratis, i WordPress arkiv). Det ger ett gränssnitt för att lägga till PHP-snuttar utan att röra temat. Snuttar kan aktiveras och inaktiveras individuellt, vilket är praktiskt för felsökning. Ett alternativ är WPCode (tidigare Insert Headers and Footers), också gratis och med omfattningskontroll; du kan binda en snutt till ett specifikt formulär via villkorslogik.
Hur kontrollerar jag att hooken faktiskt körs?
Det enklaste sättet:
error_log( 'HOOK FIRED' )inuti callback-funktionen och kontrollerawp-content/debug.logmedWP_DEBUGaktiverat. För snabb felsökning utan loggar, ersätt tillfälligtreturn $contact_formmedwp_die('Hook works'). Gör inte detta på en produktionssajt; endast på lokal miljö eller staging.
Vad ska jag göra om min kod slutar fungera efter en CF7-uppdatering?
Kontrollera först hook-signaturen. I version 5.2 ökade antalet argument för
wpcf7_before_send_mailfrån 1 till 3. Om din callback deklareras utan parametern$submission, lägg till den. För det andra, verifiera att din funktion returnerar objektet$contact_form. För det tredje, kontrollera PHP-felloggen; CF7 ignorerar tyst fatala fel inuti hooks, formuläret skickas som vanligt, och du ser inte problemet.
Finns det ett sätt att prenumerera på flera formulär med en hook?
Ja,
wpcf7_before_send_mailkörs för alla formulär. Inuti callbacken filtrerar du efter ID:$contact_form->id()returnerar ett nummer som matchar formulärets shortcode-ID (till exempel[contact-form-7 id="42"]). Jämför det med de önskade ID:na och kör olika logik viaifellerswitch.
Vad som ska ligga i temats functions vs. brytas ut till ett plugin
CF7-hooks fungerar tekniskt sett var som helst ifrån: functions.php, Code Snippets, MU-plugin. Men det finns en praktisk uppdelning som sparar huvudvärk när du byter tema eller uppdaterar.
Kod som är knuten till affärslogik (mottagarbyte, CRM-integration, databassparningar) bör ligga i ett separat plugin eller Code Snippets. Anledningen är enkel: temabyten ska inte bryta klientens mejlrutning. Fältvalidering, som ofta är knuten till temats layout och klasser, kan ligga kvar i functions.php; den förlorar ändå sin mening när temat byts.
Snuttar längre än 30 rader bör formateras som ett MU-plugin (wp-content/mu-plugins/cf7-custom.php). MU-plugins kan inte inaktiveras från adminpanelen, körs före vanliga plugins och kräver ingen aktivering; lägg bara in filen så fungerar koden.
För helt isolerade fall (ett formulär, en sajt), använd functions.php plus ett barntema. Färre filer, mindre förvirring.
Samma principer gäller för alla andra formulärplugins, oavsett om det är WPForms, Gravity Forms eller Fluent Forms. Var och en har sina egna hooks, men det arkitektoniska angreppssättet "affärslogik separat, presentationslogik med temat" är universellt.
Videon ger en steg-för-steg-genomgång av anpassad CF7-fältvalidering med ett live-exempel i WordPress adminpanel. Tillvägagångssättet är kompatibelt med filtret wpcf7_validate som beskrivs ovan, så se den som ett visuellt komplement till koden från valideringsavsnittet.



