«Ввёл все цифры, флаг — Россия, а мне пишут: введите корректный номер». Номер был правильный. Маска под флагом была правильная. Сервер проверял его по правилам другой страны.

Это 12-я часть цикла «WordPress на кэшируемом сайте».

Два источника правды

Сайт работал в нескольких странах. Страну на странице определяли два разных места:

ЧтоОткуда берёт страну
маска поля и флагразметка страницы: <meta name="language">
проверка номера на серверекука lang из запроса

Обычно они совпадают. Но разметка приходит из кэша и живёт своей жизнью, а кука — общая для всех вкладок и меняется мгновенно. Расходятся они легко:

  • страница открыта из истории браузера кнопкой «назад», а кука уже другая;
  • в соседней вкладке сменили страну — кука сменилась у всех вкладок;
  • страну переключили без перезагрузки страницы.

В итоге под флагом «Россия» сервер проверял номер по белорусскому шаблону и отвергал правильный +7.

Воспроизводится за минуту: поставить куку lang=by из консоли, не перезагружая страницу, и отправить корректный российский номер.

Вторая мина в том же коде

return preg_match($regExps[$lang], $phone); // $lang — из куки

Список стран задаёт контент-менеджер в настройках. Если в куке окажется страна, которой нет в списке шаблонов, — отвергаться будет каждый номер.

Решение: любой известный формат

Мы не стали чинить синхронизацию куки и разметки. Правило из прошлой части — форма должна отправиться всегда — подсказывает решение проще: номер принимается, если он подходит под шаблон любой из известных стран.

function validate_phone(string $phone, array $regExps): bool
{
    foreach ($regExps as $regExp) {
        if (preg_match($regExp, $phone)) {
            return true;
        }
    }
    return false;
}
  • недозаполненный номер по-прежнему отвергается: он не подходит ни под один шаблон;
  • передавать страну с клиента отдельным полем смысла нет — при проверке «любой известный» результат тот же;
  • лишняя заявка с номером соседней страны дешевле потерянной.

Общий урок для кэшируемых сайтов

Если страница из кэша и сервер решают одно и то же по разным источникам, однажды они разойдутся. Разметка застыла на момент кэширования, кука — живая. Либо оба решения берут одно и то же (например, страна передаётся из разметки вместе с формой), либо сервер не должен зависеть от того, в чём они расходятся.

Как кука в разметке вообще ломает кэш — в девятой части цикла про кэш страниц.

Посетители не могут отправить форму с правильным телефоном?

Пришлите адрес — проверю, по каким правилам сервер проверяет номер и откуда их берёт.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.