Как сделать проверку (валидацию) на номер телефона в WordPress на PHP?

Эта заметка относится к разряду технической. То есть уже требует небольшого погружения в код .

Дано: Сайт под управлением CMS WordPress.

Задача: Проверить на уровне сервера (на стороне back-end) данные приходящие извне, на корректный номер телефона.

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

Давайте взглянет на класс WC_Validation. В нём мы увидим нужные нам методы для решения поставленной задачи:

  • is_phone()Проверяет номер телефона с помощью регулярного выражения.
  • format_phone()Позволяет отформатировать переданный номер телефона.

Давайте взглянем на этот метод из ядра плагина WooCommerce:

/**
* Validates a phone number using a regular expression.
*
* @param  string $phone Phone number to validate.
* @return bool
*/
public static function is_phone( $phone ) {
	if ( 0 < strlen( trim( preg_replace( '/[\s\#0-9_\-\+\/\(\)\.]/', '', $phone ) ) ) ) {
		return false;
	}

	return true;
}

Очевидно, что метод реализует грамотную проверку на адекватный номер телефона.

Функция strlen() возвращает длину строки и тут же мы её проверяем , чтобы она не была меньше нуля. А функция trim() ещё раньше отрабатывает и её назначение — удалить пробелы из начала и конца строки. И в серединке мы видим функцию preg_replace(), которая осуществляет поиск и замену по регулярному выражению. Первый аргумент — это паттерн. Второй аргумент — это то, что функция получает, то есть наш номер телефона извне. Возвращает функция булев тип: true|false.

Применение:

В принципе, для того чтобы воспользоваться функцией можно просто вызвать её, передав ей данные на валидацию. Но я предлагаю другой подход. Мы её вынесем отдельно, как функцию-хелпер, но только с проверкой на объявление одноимённой функции (можно конечно просто переименовать произвольно и не заморачиваться, но я учёл, что может быть активирован плагин Woo и тогда выполнение вызова функции, будет уже на стороне Woo).

/**
* Validates a phone number using a regular expression.
*
* @param  string $phone Phone number to validate.
* @return bool
*/
if (!function_exists('is_phone')) {
	function is_phone( $phone ) {
		if ( 0 < strlen( trim( preg_replace( '/[\s\#0-9_\-\+\/\(\)\.]/', '', $phone ) ) ) ) {
			return false;
		}
	
		return true;
	}
}

Предлагаю прибегнуть к помощи онлайн-инструмента PHP Online Compiler (Editor / Interpreter) и посмотреть наш код в действии.

Я специально подготовил данные с разными вариантами: слитно со знаком «плюс», с чёрточками и с пробелом (последний пример). Люди по разному могут указать номер телефона. Все примеры валидны.

А теперь давайте рассмотрим не валидный пример, в котором специально вместо нуля передал заглавную «O», а в двух следующих специальные символы, которые не учтены в паттерне регулярного выражения. В итоге получили false

Форматирование номера телефона

Вторая функция format_phone(), которая идёт «прицепом» к первой, является обёрткой функции wc_format_phone_number()

Обратите внимание, что внутри после проверки на пустую строку идёт проверка и привязка к ранее рассмотренной функции. Согласно коду — это метод класса WC_Validation и он должен быть не false. Тогда то и происходит магия при помощи регулярного выражения и другого паттерна. Задумка хорошая, но по большому счёту для нашего континента бесполезная 🙂

При желании можно конечно «допилить» это дело, например, оформить в отдельную функцию-хелпер или же дополнить код первой функции и получить полное решение валидации номера телефона с последующим форматированием при возврате функцией. Хорошей отправной точкой тут может послужить нативная функция PHP sscanf() — которая разбирает строку в соответствии с заданным форматом. Вот пример со страницы описания данной функции.

Естественно, что для начинающих пользователей это может показаться сложным решением, поэтому я предлагаю написать простенькую «функцию-прицеп» к нашей первой функции-валидатору, которая будет возвращать отформатированную строку.

/**
 * Format phone numbers.
 *
 * @param string $phone Phone number.
 * @return string
 */
function myFormatPhone( $phone ) {
	$phone = $phone ?? '';
    
    $count = iconv_strlen($phone, 'UTF-8');
    
    if($count === 10){
    
    	$part_one = substr($phone, 0, 3); // 903
    	$part_two = substr($phone, 3, 3); // 000
    	$part_three = substr($phone, 6, 2); // 00
    	$part_four = substr($phone, 8, 2); // 00   
        
        $phone = "({$part_one}) {$part_two}-{$part_three}-{$part_four}";
        
    }

	return $phone;
}
результат выполнения

Код не идеальный. Это просто импровизация для того чтобы показать, как просто на стороне «бэкэнд», на PHP можно сделать форматирование возвращаемой строки с номером телефона.

Здесь для демонстрации возможностей PHP для каких-то проверок/условий задействовал функцию iconv_strlen() — возвращает количество символов в строке, а не количество байт (как, например strlen()).

Если отталкиваться от этого кода, то тут нужно учесть, что первая наша функция разрешает символы «+» и «-» , а следовательно их подсчёт тоже будет учитываться и нас подстерегает неожиданность при форматировании 🙂 Поэтому, в этом случае имеет смысл передавать только цифры, а всё лишнее — вычищать. Следовательно, наше выражение может иметь в первой функции следующий вид:

preg_replace("/[^0-9]/","", $phone ........

Но тут опять много нюансов, например человек может начать запись с «8-ки», а может с «7-ки» 🙂 А в Казахстане формат встречается зачастую +7 (7xx) xxx-xx-xx

Поэтому можно сохранять в базу значение до форматирования, а потом ещё и после и в случае каких-то непонятных ситуаций исследовать эти значения.

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

Но, если вы всё-таки намерены делать форматирование, то я предлагаю реализовать его на стороне клиента и для этого можно задействовать изящное решение под WooCommerce, при помощи которого мы можем задать нужную маску для ввода номера телефона пользователем перед тем, как он будет передаваться функции-валидатору.

Как сделать маску при вводе номера телефона?

Автор

Evgeni

Веб-разработчик, фрилансер и фанат WordPress с 2012 года. На этом сайте делюсь заметками для начинающих по разработке на WordPress. Надеюсь увидеть вас в числе своих подписчиков.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *