
🚀 Wie man sich in Contact Form 7 vor dem Absenden des Formulars einklinkt
Contact Form 7 ist auf Millionen von WordPress-Websites installiert. Es ist einfach, zuverlässig und kostenlos. Doch sobald das Standardverhalten nicht mehr ausreicht und Sie ein Feld validieren, einen dynamischen Empfänger festlegen oder eine E-Mail basierend auf einer Bedingung abbrechen müssen, betreten Sie das Terrain der Frage: „Wie macht man das überhaupt?"
Die CF7-Dokumentation beschreibt Hooks nur kurz. Foren und Stack Overflow sind voll mit Code-Snippets für alte Plugin-Versionen, und fünf Jahre alter Code bricht unter modernem CF7 stillschweigend. Lassen Sie uns herausfinden, welche Hooks heute aktuell sind und wie Sie sich ohne Überraschungen einklinken.
💡 Kurzer Überblick:
- Der wichtigste Hook ist
wpcf7_before_send_mail, der Einstiegspunkt für jede Logik vor dem Versand. - Sie können die E-Mail mit dem Filter
wpcf7_skip_mailoder einer einzigen Zeileskip_mail: onin den Formulareinstellungen überspringen. - Um übermittelte Daten zu erhalten, nutzen Sie das
$submission-Objekt und die Methodeget_posted_data(). - Um den Empfänger dynamisch zu ändern, verwenden Sie
set_properties()am Formularobjekt. - Für die Feldvalidierung nutzen Sie
wpcf7_validatemit einem Filter nach Feldtyp.
Warum Sie Pre-Send-Hooks benötigen
Das Standard-CF7-Szenario sieht so aus: Ein Nutzer füllt Felder aus, klickt auf „Absenden", das Plugin sendet eine E-Mail an eine feste Adresse. Das war's. Logik in diesen Prozess einzubauen, ist ohne Hooks unmöglich.
Der Hook wpcf7_before_send_mail und verwandte Filter erlauben es Ihnen, genau in dem Moment in die Kette einzugreifen, in dem die Daten validiert wurden, die E-Mail aber noch nicht versendet ist. Sie können:
- eine benutzerdefinierte Bedingung prüfen und die Übermittlung abbrechen;
- Formulardaten in einer Datenbank oder externen API speichern;
- den E-Mail-Empfänger spontan ändern;
- den E-Mail-Inhalt anpassen;
- eine Integration mit einem CRM oder E-Mail-Marketing-Dienst auslösen.
Alle folgenden Beispiele funktionieren mit Contact Form 7 Version 5.2 und höher. Sollte Ihr Plugin älter sein, aktualisieren Sie es zuerst: Alte Hook-Signaturen sind inkompatibel.
Wpcf7_before_send_mail, der Einstiegspunkt
Ab Version 5.2 hat sich die Hook-Signatur geändert. Zuvor wurde nur das Formularobjekt übergeben, jetzt sind es drei Argumente:
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 }
Datei für die Platzierung: functions.php Ihres aktiven Themes oder das Plugin Code Snippets. Die Priorität 10 funktioniert für die meisten Aufgaben; erhöhen Sie sie auf 1, wenn Ihr Callback vor anderen laufen muss, oder senken Sie sie auf 99, wenn er danach laufen soll.
Beachten Sie, dass dieser Hook ein Filter ist, keine Action. Sie müssen das $contact_form-Objekt (oder WPCF7_ContactForm) zurückgeben, andernfalls wird die Kette fehlerhaft unterbrochen.
E-Mail-Versand überspringen
Der häufigste Anwendungsfall: Keine Benachrichtigung senden, wenn ein Feld auf eine bestimmte Weise ausgefüllt ist. Es gibt zwei Ansätze.
Den wpcf7_skip_mail-Filter verwenden
Kurz und sauber. Der Filter akzeptiert einen booleschen Wert und das Formularobjekt:
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 }
Die Methode WPCF7_Submission::get_instance() bietet innerhalb dieses Filters Zugriff auf die Übermittlungsdaten. Ohne sie ist get_posted_data() nicht verfügbar, da $submission nicht direkt an wpcf7_skip_mail übergeben wird.
Zusätzliche Einstellungen verwenden
Wenn die Logik so einfach wie möglich ist (E-Mail für ein bestimmtes Formular immer überspringen), gehen Sie ins Admin-Panel. Fügen Sie im Tab „Zusätzliche Einstellungen" des Formulars eine Zeile hinzu:
1 skip_mail: on
Kein Code erforderlich. Das Plugin stoppt den E-Mail-Versand direkt nach der Validierung, und der Nutzer sieht eine Erfolgsmeldung. Perfekt für Demo-Formulare und Testumgebungen.
Eine Alternative mit demselben Effekt: demo_mode: on. Der Unterschied besteht darin, dass demo_mode den Erfolg vollständig simuliert, ohne das Mail-Subsystem zu berühren, während skip_mail nur den Versandschritt überspringt und das gesamte übrige Verhalten beibehält.
Übermittelte Daten abrufen
Das $submission-Objekt (das dritte Argument von wpcf7_before_send_mail) gibt vollen Zugriff auf das, was der Nutzer übermittelt hat:
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 }
Feldschlüssel ('your-name', 'your-email') sind die Werte des name-Attributs in den Formular-Shortcodes. Standard-Tags wie [text* your-name], [email* your-email] erzeugen Schlüssel ohne Präfixe; übernehmen Sie einfach das, was nach dem Leerzeichen steht.
Wichtig: get_posted_data() liefert Rohdaten vor der Verarbeitung durch E-Mail-Vorlagen. Sonderzeichen, Zeilenumbrüche, alles so, wie der Nutzer es eingegeben hat. Bereinigen Sie die Daten vor dem Speichern in der Datenbank mit sanitize_text_field() oder ähnlichen Funktionen.
Dynamische Empfängerumschaltung
Angenommen, die E-Mail soll je nach dem im Formular gewählten Thema an unterschiedliche Sachbearbeiter gehen. Wir ändern die Eigenschaft recipient spontan:
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 }
Die Methoden get_properties() und set_properties() arbeiten mit dem Einstellungs-Array des Formulars, einschließlich des Abschnitts mail. Sie können nicht nur den Empfänger ändern, sondern auch den Betreff (subject), den Inhalt (body), zusätzliche Header (additional_headers) und den Absender (sender).
Platzieren Sie den Code am selben Ort: in der functions.php Ihres Themes oder via Code Snippets. Testen Sie auf einer Staging-Umgebung, bevor Sie in Produktion gehen: Ein Tippfehler im Schlüssel des mail-Arrays wird stillschweigend ignoriert, und die E-Mail geht an die Standardadresse.
Feldvalidierung vor dem Senden
CF7 bietet den Filter wpcf7_validate, der vor wpcf7_before_send_mail ausgelöst wird. Er erhält ein WPCF7_Validation-Objekt und erlaubt es Ihnen, einen Fehler hinzuzufügen; das Formular wird erst abgeschickt, wenn der Nutzer ihn korrigiert hat:
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 }
Der Filter wird nach dem Muster wpcf7_validate_<field type> benannt: text* für Pflicht-Textfelder, email* für E-Mail, textarea* für Textbereiche. Ohne das Sternchen gilt er für optionale Felder. $tag ist ein Objekt mit den Parametern des Formularfelds, einschließlich name.
Fehler werden mit der Methode invalidate($tag, 'error text') hinzugefügt. Der Text ist frei wählbar und wird unter dem Formularfeld angezeigt. Bei AJAX-Übermittlung (dem Standard in CF7) erscheint die Meldung ohne Neuladen der Seite.
⁉️🤔 Häufig gestellte Fragen
Was ist der Unterschied zwischen wpcf7_before_send_mail und wpcf7_mail_sent?
wpcf7_before_send_mailwird vor dem E-Mail-Versand ausgelöst; Sie können die E-Mail abbrechen, den Empfänger ändern oder Daten darin anpassen.wpcf7_mail_sentist eine Action, die nach erfolgreichem Versand ausgelöst wird. Nutzen Sie sie für Logging, das Auslösen von Webhooks oder Datenbankschreibvorgänge, wenn die E-Mail garantiert versendet wurde. Wenn Sie den Prozess unterbrechen müssen, funktioniert nurbefore_send_mail.
Kann ich mich einklinken, ohne functions.php zu bearbeiten?
Ja, über das Plugin Code Snippets (kostenlos, im WordPress-Repository). Es bietet eine Oberfläche zum Hinzufügen von PHP-Snippets, ohne das Theme zu berühren. Snippets können einzeln aktiviert und deaktiviert werden, was für die Fehlersuche praktisch ist. Eine Alternative ist WPCode (ehemals Insert Headers and Footers), ebenfalls kostenlos und mit Gültigkeitsbereichssteuerung; Sie können ein Snippet durch bedingte Logik an ein bestimmtes Formular binden.
Wie prüfe ich, ob der Hook tatsächlich ausgelöst wird?
Der einfachste Weg:
error_log( 'HOOK FIRED' )innerhalb der Callback-Funktion und Prüfung vonwp-content/debug.logbei aktiviertemWP_DEBUG. Für schnelle Fehlersuche ohne Logs ersetzen Sie vorübergehendreturn $contact_formdurchwp_die('Hook works'). Tun Sie dies nicht auf einer Produktivseite, sondern nur in lokalen oder Staging-Umgebungen.
Was tun, wenn mein Code nach einem CF7-Update nicht mehr funktioniert?
Prüfen Sie zuerst die Hook-Signatur. In Version 5.2 stieg die Anzahl der Argumente für
wpcf7_before_send_mailvon 1 auf 3. Wenn Ihr Callback ohne den Parameter$submissiondeklariert ist, fügen Sie ihn hinzu. Zweitens: Stellen Sie sicher, dass Ihre Funktion das$contact_form-Objekt zurückgibt. Drittens: Prüfen Sie das PHP-Fehlerprotokoll; CF7 ignoriert schwerwiegende Fehler innerhalb von Hooks stillschweigend, das Formular wird wie gewohnt abgeschickt, und Sie sehen das Problem nicht.
Gibt es eine Möglichkeit, mit einem Hook mehrere Formulare zu abonnieren?
Ja,
wpcf7_before_send_mailwird für alle Formulare ausgelöst. Filtern Sie innerhalb des Callbacks nach ID:$contact_form->id()gibt eine Nummer zurück, die der Formular-Shortcode-ID entspricht (zum Beispiel[contact-form-7 id="42"]). Vergleichen Sie sie mit den benötigten IDs und führen Sie unterschiedliche Logik perifoderswitchaus.
Was in Theme-Functions gehört vs. in ein Plugin ausgelagert werden sollte
CF7-Hooks funktionieren technisch von überall: functions.php, Code Snippets, MU-Plugin. Aber es gibt eine praktische Aufteilung, die Kopfschmerzen bei Theme-Wechseln oder Updates erspart.
Code, der mit Geschäftslogik verbunden ist (Empfängerumschaltung, CRM-Integration, Datenbankspeicherungen), sollte in ein separates Plugin oder Code Snippets. Der Grund ist einfach: Ein Theme-Wechsel sollte die E-Mail-Weiterleitung des Kunden nicht unterbrechen. Feldvalidierung, die oft mit Theme-Layout und -Klassen verknüpft ist, kann in functions.php bleiben; sie verliert bei einem Theme-Wechsel ohnehin ihre Bedeutung.
Snippets, die länger als 30 Zeilen sind, sollten als MU-Plugin formatiert werden (wp-content/mu-plugins/cf7-custom.php). MU-Plugins können nicht über das Admin-Panel deaktiviert werden, werden vor regulären Plugins ausgeführt und benötigen keine Aktivierung; einfach die Datei ablegen, und der Code funktioniert.
Für vollständig isolierte Fälle (ein Formular, eine Website) verwenden Sie functions.php plus ein Child-Theme. Weniger Dateien, weniger Verwirrung.
Dieselben Prinzipien gelten für jedes andere Formular-Plugin, sei es WPForms, Gravity Forms oder Fluent Forms. Jedes hat seine eigenen Hooks, aber der architektonische Ansatz „Geschäftslogik getrennt, Präsentationslogik beim Theme" ist universell.
Das Video bietet eine schrittweise Aufschlüsselung der benutzerdefinierten CF7-Feldvalidierung mit einem Live-Beispiel im WordPress-Admin-Panel. Der Ansatz ist kompatibel mit dem oben beschriebenen Filter wpcf7_validate, sehen Sie es sich daher als visuelle Ergänzung zum Code aus dem Validierungsabschnitt an.



