Задача. Есть большой список телефонных номеров, которые нужно переформатировать под единый формат (или форматы). Номера есть нескольких типов 7, 10 и 11 значные. Для каждого из этих типов необходимо вывести номер телефона в своем формате.

В php есть такие функции как money_format и number_format, но нет такой функции как phone_format, этот пробел я и решил восполнить написав такую функцию для форматирования телефонных номеров.

/**
 * Форматирование телефонного номера
 * по шаблону и маске для замены
 *
 * @param string $phone
 * @param string|array $format
 * @param string $mask
 * @return bool|string
 */
function phone_format($phone, $format, $mask = '#')
{
    $phone = preg_replace('/[^0-9]/', '', $phone);

    if (is_array($format)) {
        if (array_key_exists(strlen($phone), $format)) {
            $format = $format[strlen($phone)];
        } else {
            return false;
        }
    }

    $pattern = '/' . str_repeat('([0-9])?', substr_count($format, $mask)) . '(.*)/';

    $format = preg_replace_callback(
        str_replace('#', $mask, '/([#])/'),
        function () use (&$counter) {
            return '${' . (++$counter) . '}';
        },
        $format
    );

    return ($phone) ? trim(preg_replace($pattern, $format, $phone, 1)) : false;
}

Использование

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

$phones = array(
    '926 111-2233',
    '9261112233',
    '8 (926) 111 22 33',
    '8 926 111-22-33',
    '559-8833',
    '5598833',
    '',
    'qweqwe'
);

$formats = array(
    '7' => '###-##-##',
    '10' => '+7 (###) ### ####',
    '11' => '# (###) ### ####'
);

foreach ($phones AS $phone) {
    echo phone_format($phone, $formats, '#');
}

Результат выполнения радует глаз:

+7 (926) 111 2233
+7 (926) 111 2233
8 (926) 111 2233
8 (926) 111 2233
559-88-33
559-88-33

Данный сниппет не ставит перед собой цель определить город, регион или какой-либо другой параметр. Кроме того возникнут проблемы при использовании шаблонов для номеров “8 (123) 111-22-33” и “+7 (123) 111-22-33”. Возможно потом придумаю как поступать с такими номерами.