Ситуация типовая: форма визуально выглядит рабочей, письмо уходит, но в заявках регулярно оказывается пустой или мусорный телефон. Для отдела продаж это почти всегда означает лишнюю ручную проверку, а иногда и потерянные лиды, если форма не должна отправляться без контакта.
В Contact Form 7 есть базовая обязательность полей, но на практике этого не всегда достаточно. Поле могут скрыть стилями, подставить некорректное значение автозаполнением, а иногда проблема вообще не в верстке, а в том, что форма собирается из нескольких шаблонов и в одном из них правило обязательности забыли добавить.
Когда проблема действительно в валидации, а не в шаблоне
Сначала стоит понять, где ломается логика: в разметке формы, в настройках CF7 или в кастомном коде. Если телефон не обязателен, форма отправляется даже с пустым значением. Если поле отмечено как обязательное, но отправка все равно проходит, значит, либо правило не применилось к конкретному тегу, либо его перехватывает тема/плагин.
Что проверить в первую очередь
- в форме используется именно обязательный тег, а не обычный текстовый;
- в шаблоне нет второго поля с тем же именем;
- маска телефона не очищает значение до пустой строки перед отправкой;
- кастомный JavaScript не снимает атрибуты валидации;
- в письме и в базе не подставляется значение по умолчанию вместо реального ввода.
Если телефон нужен только для части форм, не пытайтесь решать это глобально через CSS. Нужна проверка на уровне конкретной формы или серверной валидации, иначе обход будет слишком простым.
Пошаговое решение через стандартные теги Contact Form 7
Самый надежный вариант — сделать поле обязательным прямо в разметке формы. Для телефона используйте тег tel*. Звездочка здесь важна: она включает обязательность на стороне CF7.
[text* your-name placeholder "Имя" ]
[tel* your-phone placeholder "Телефон" ]
[email your-email placeholder "Email"]
[textarea your-message placeholder "Сообщение"]
[submit "Отправить"]Если у вас уже стоит обычный [tel your-phone], замените его на [tel* your-phone]. После этого CF7 не должен пропускать отправку без значения в поле телефона.
Но если вы используете маску ввода, проверьте, не превращает ли она пустой ввод в символы вроде + или пробелы. В таком случае форма может считаться заполненной, хотя реального номера нет. Тогда нужна серверная проверка.
Серверная проверка телефона через хук wpcf7_validate_tel*
Если нужно отсеивать не просто пустое поле, а еще и мусор вроде 123 или +7 (___) ___-__-__, лучше добавить валидацию в PHP. Так вы не зависите от JavaScript и масок.
add_filter( 'wpcf7_validate_tel*', 'cf7_validate_required_phone', 20, 2 );
add_filter( 'wpcf7_validate_tel', 'cf7_validate_required_phone', 20, 2 );
function cf7_validate_required_phone( $result, $tag ) {
$field_name = $tag->name;
if ( 'your-phone' !== $field_name ) {
return $result;
}
$value = isset( $_POST[ $field_name ] ) ? trim( wp_unslash( $_POST[ $field_name ] ) ) : '';
$digits = preg_replace( '/\D+/', '', $value );
if ( '' === $value || strlen( $digits ) < 10 ) {
$result->invalidate( $tag, 'Укажите корректный номер телефона.' );
}
return $result;
}Здесь логика простая: если поле пустое или в нем слишком мало цифр, отправка блокируется. Порог 10 цифр подходит не для всех стран, поэтому подстройте его под свой сценарий. Если у вас международные заявки, лучше проверять формат более гибко, а не жестко по длине.
Когда этот способ лучше стандартной обязательности
Он полезен, если:
- телефон проходит через маску и обычная проверка не ловит пустые значения;
- нужно запретить короткие или заведомо неверные номера;
- форма собирается из нескольких источников и вы хотите единое правило на сервере;
- JavaScript на странице может отключаться или конфликтовать с темой.
Если телефон должен быть обязателен только в одной форме
Не всегда нужно вешать проверку на все формы сайта. У Contact Form 7 можно ограничить логику по ID формы, чтобы не сломать другие сценарии. Это особенно важно, если на сайте есть форма обратной связи, заявка на консультацию и форма подписки, где телефон вообще не нужен.
add_filter( 'wpcf7_validate_tel*', 'cf7_validate_phone_only_for_one_form', 20, 2 );
function cf7_validate_phone_only_for_one_form( $result, $tag ) {
$submission = WPCF7_Submission::get_instance();
if ( ! $submission ) {
return $result;
}
$contact_form = wpcf7_get_contact_form_by_post_id( $submission->get_contact_form_id() );
if ( ! $contact_form || 123 !== (int) $contact_form->id() ) {
return $result;
}
if ( 'your-phone' !== $tag->name ) {
return $result;
}
$value = isset( $_POST['your-phone'] ) ? trim( wp_unslash( $_POST['your-phone'] ) ) : '';
if ( '' === $value ) {
$result->invalidate( $tag, 'Телефон обязателен.' );
}
return $result;
}Замените 123 на ID нужной формы. Такой подход удобен, когда на сайте уже есть несколько форм и не хочется менять их все одновременно.
Сравнение подходов: что выбрать на практике
| Подход | Когда подходит | Ограничения |
|---|---|---|
Только tel* в форме | Нужно просто сделать поле обязательным | Не ловит мусорные значения и проблемы с маской |
PHP-валидация через wpcf7_validate_tel* | Нужна надежная проверка на сервере | Требует правки темы или мини-плагина |
| Проверка по ID формы | Правило нужно только для одной заявки | Нужно следить за ID при переносе формы |
Как проверить, что решение сработало
Проверка должна быть не формальной, а по сценарию. Отправьте форму в трех вариантах: с пустым телефоном, с явно неверным номером и с корректным значением. В первом и втором случае отправка должна блокироваться, а в третьем — проходить.
- Пустое поле: форма не отправляется, появляется текст ошибки.
- Номер из 2–3 цифр: форма тоже не проходит, если включена серверная проверка.
- Нормальный номер: письмо уходит, сообщение об успехе отображается.
Дополнительно откройте инструменты разработчика и убедитесь, что в ответе CF7 нет скрытых ошибок JavaScript. Если форма визуально блокируется, но письмо все равно уходит, значит, проверка работает только на фронтенде и ее нужно дублировать на сервере.
Частые ошибки и как их исправить
Оставили обычный тег вместо обязательного
Если в форме стоит [tel your-phone], Contact Form 7 не будет считать поле обязательным. Решение простое: заменить на [tel* your-phone].
Маска телефона подставляет символы в пустое поле
Некоторые маски оставляют +, скобки или пробелы. Визуально поле выглядит заполненным, но реального номера нет. В этом случае нужна серверная проверка с очисткой от нецифровых символов.
Проверка висит на всех формах сразу
Если вы добавили фильтр без ограничения по ID формы, он начнет влиять на все формы сайта. Это ломает подписки, заявки и тестовые формы. Привязывайте правило к конкретной форме, если сценарий точечный.
Ошибка появляется, но форма все равно отправляется
Так бывает, когда в коде неправильно используется invalidate или фильтр подключен не к тому типу поля. Проверьте имя тега и тип фильтра: для телефона нужен именно wpcf7_validate_tel* или wpcf7_validate_tel.
Что учесть по безопасности и производительности
Не вставляйте проверку в functions.php активной темы, если сайт часто обновляется или тема может меняться. Практичнее вынести код в небольшой mu-plugin или отдельный мини-плагин. Так правило не исчезнет после обновления темы.
Если на сайте много форм, не плодите несколько одинаковых фильтров в разных местах. Один аккуратный обработчик проще сопровождать и легче отлаживать. И не забывайте, что серверная валидация не заменяет антиспам: пустые и мусорные телефоны она отсечет, но ботов полностью не остановит.
Если вам нужно дополнительно чистить сайт от дублей и лишней нагрузки, иногда полезно посмотреть в сторону инструментов вроде Clearfy Pro, но для самой задачи обязательного телефона это не требуется. Здесь важнее корректная схема валидации и отсутствие конфликтов между маской, темой и CF7.
После внедрения сохраните рабочий фрагмент кода отдельно и проверьте форму после обновления плагина Contact Form 7. Если форма использует кастомный шаблон, повторно тестируйте ее после любых правок разметки: именно там чаще всего теряется обязательность поля.