Помилка входу, спричинена невідповідністю форматів зберігання номерів телефонів, виявила недолік. Обліковий запис одного користувача було заблоковано, оскільки в базі даних один і той самий німецький мобільний номер зберігався у двох форматах — 0171 5550134 в одному рядку та +49 171 5550134 в іншому — тому система сприйняла їх як різні записи. Результат: OTP-код ніколи не надійшов, а кнопка «надіслати код» перетворилася на лотерею.
Чому номери телефонів складніші за дати
Розробники часто покладаються на regex, щоб приборкати введення номерів телефонів. Ця довіра руйнується в ту саму мить, коли номер перетинає кордон або змінюється національний план нумерації. Дати слідують передбачуваному календарю; номери телефонів змінюються разом із операторами, правилами та культурними традиціями.
Прихована вартість необроблених рядків
Зберігання номера телефону як звичайного рядка здається унікальним — доки два представлення не вкажуть на один і той самий запис. OTP-системи, які роблять запит до бази даних за «тим самим» номером, зрештою надсилають код на дублікат, який ніколи не дійде до користувача.
Проблема посилюється, коли номери зберігаються в числових полях. Стовпець BIGINT видаляє знак + та будь-які початкові нулі, перетворюючи +49 171 5550134 на 491715550134. Без знака «плюс» відновлення оригінального формату стає вгадуванням.
Контракт E.164
Міжнародний план телефонної нумерації E.164 визначає єдине, універсальне представлення:
- Починається з
+ - Далі йде 1-3-значний код країни
- Потім номер абонента
- Не більше 15 цифр загалом
- Жодних пробілів, крапок чи дефісів
E.164 не гарантує, що номер активний; він лише гарантує, що рядок відповідає правильному структурному шаблону. Ставтеся до нього як до контракту щодо формату, а не як до оракула доступності.
Поширені пастки, які не може виправити regex
- Числове зберігання —
BIGINTвідкидає+та початкові нулі. Використовуйте замість цього текстовий стовпець (TEXTабоVARCHAR). - Захардкоджені regex — національні плани змінюються. Мексика скасувала свій транзитний префікс у 2019 році; Аргентина тепер вимагає цифру
9після коду країни для мобільних ліній. Статичний шаблон швидко застаріває. - Сліпе видалення нулів — італійські стаціонарні телефони зберігають початковий нуль, німецькі — ні. Правило «видалити всі початкові нулі» зіпсує італійські дані, не зачепивши німецькі номери.
- Припущення, що формат означає доставку —
libphonenumberперевіряє структуру, але не може сказати, чи увімкнено телефон чи чи був перенесений номер.
Побудова надійного конвеєра
- Запитуйте країну — додайте селектор країни у форми реєстрації та передавайте цей регіон парсеру.
- Показуйте форматування в реальному часі — використовуйте форматування типу “AsYouType”, щоб користувачі бачили правильний шаблон під час введення.
- Валідуйте при втраті фокусу (on blur) — запускайте валідацію після того, як користувач залишає поле, а не при кожному натисканні клавіші; це зменшує тертя.
- Зберігайте лише рядок E.164 — зберігайте нормалізований номер із префіксом
+у базі даних. - Форматуйте на рівні інтерфейсу — повертайтеся до зручного для людини формату лише в UI або шаблонах електронних листів.
При міграції застарілих даних зберігайте рядки, які не пройшли валідацію. Розберіть кожен існуючий запис у новий стовпець, позначте помилки та створіть звіт. Тихе видалення даних створює запити в службу підтримки, які згодом перетворюються на дорогі виправлення.
Швидкий чек-лист для розробників
- Зберігайте номери як
TEXT/VARCHARу форматі E.164. - Використовуйте бібліотеку Google libphonenumber; вона справляється з хаотичною реальністю глобальних планів нумерації.
- Забезпечуйте регіон за замовчуванням для користувачів, які пропускають код країни.
- Викликайте
is_valid_numberдля реєстрацій у реальному часі; вона перевіряє, чи відповідає номер регіональним правилам. - Використовуйте
is_possible_numberпід час очищення масивів даних; вона виявляє явно некоректні записи, не відхиляючи граничні випадки.
Правильна обробка номерів телефонів — це не просто приємне доповнення, а необхідна умова для будь-якої системи, що покладається на надійний контакт із користувачем. Нормалізуючи дані до E.164 та делегуючи парсинг перевіреній бібліотеці, розробники усувають цілий клас багів, які непомітно підривають довіру та прибуток. Ставтеся до номерів телефонів як до структурованих даних, а не як до вільного тексту, і дозвольте стандартам виконувати важку роботу.
