PHP — Как сделать телефон из строки по маске
Получаем телефон из поля, который записан в виде цифр — 73123123123, и форматируем его в более читаемый вид — 7 (312) 312-31-23.
При помощи функции форматирования строки sprintf и функции substr выводим наш набор цифр в более читаемый вид. Хорошо если на вашем сайте установлена js маска, и все телефоны подгоняются сразу под нужный формат. Но там где этого нет на помощь может прийти PHP.
Первым параметром мы задаем маску, размечая части при помощи %s. Обратите внимание, в самой маске вы можете задать различные символы, главное правильно «порезать» наш телефон.
При помощи substr формируем нужные нам отрезки строки — первый параметр это наша строка ($from), второй параметр это с какого символа вырезаем, и, тут внимание, сколько символов берем после второго параметра. Не путайте, это не промежуток от символа до символа.
Надеюсь у вас всё получилось 🙂
автор: Dmitriy
Занимаюсь веб-разработкой с 2011 года. Посмотреть некоторые из моих работ, а также узнать чуть больше обо мне, вы можете на forwww.ru.
— Создание сайтов на 1С-Битрикс любой сложности
— Вёрстка макетов Figma, Photoshop, Zeplin
— Поддержка проектов на Битриксе
— Разработка нового функционала для сайта
— Парсинг данных
— Выгрузка из файлов в формате XML, YML, XLS, XLSX, CSV, JSON
— Интеграция по API со сторонними сервисами
и многое другое
Форматирование телефонных номеров на PHP
Возникла задача автоматического форматирования телефонных номеров в виде страна (город) номер, и первым делом я обратился к существующим решениям.
К сожалению, оказалось, что все найденные решения основываются на обычном подгоне строки под пользовательский формат, имея ограниченную область применения и ошибки при выходе за ее пределы.
Для начала приведу обзор найденных решений. Тем, кому это не интересно, рекомендую прокрутить ниже до заголовка «Форматы телефонных номеров» — там уже представлен мой вариант разбора номера с ссылкой на код.
Всеуничтожающий примитив
Один из простых вариантов шустрого форматирования телефонных номеров, но каждое такое решение ориентировано на телефонные номера из конкретной локальной зоны и не является решением задачи.
Форматирование с помощью sscanf
Не смотря на простое решение, эта функция уже умеет форматировать номера длиной 7, 10 и более цифр, но попадись ей номер из российской глубинки, она подавится и выдаст ошибочный результат.
Symfony, lib/helpers/PhoneHelper.php, format_phone
Функция позволяет не только форматировать в XXX-XXXX, (XXX) XXX-XXXX и X (XXX) XXX-XXXX, но и конвертировать номера, написанные цифрами. Ограниченность функции в форматировании номеров длиной 7, 10 и 11 символов никак не подходит.
Форматы телефонных номеров
Из вики-статьи видно, что никакого простого и удобного паттерна для быстрого форматирования всех номеров не существует. Коды стран регистрируются, подобно доменным зонам, а коды городов — остаются на совести каждой из стран.
Другими словами, маршрутизация звонков идет по маске, начиная с кода страны: звонок, направленный в конкретную страну далее пробивает себе маршрут в соответствии с кодами области, города, района и т.д. начиная с самой левой цифры, пока последнее звено не перебросит его на конкретный телефонный/факсовый аппарат. Проблема усложняется еще и тем, что коды городов внутри стран точно так же не поддаются единой сквозной стандартизации, т.е. в худшем из вариантов для правильного форматирования номеров придется использовать двумерный массив с кодами стран и их городов.
На самом деле, все оказалось не так страшно. В каждой стране можно разделить все коды городов на две части: на те, что в большинстве своем совпадают по длине, и все остальные. Этого достаточно, чтобы резко сократить область перебора кодов при сравнении. Т.е. можно создать массив из данных по каждой стране вида:
// тесты
echo phone( «+38 (044) 226-22-04» ). «
» ;
echo phone( «0038 (044) 226-22-04» ). «
» ;
echo phone( «+79263874814» ). «
» ;
echo phone( «4816145» ). «
» ;
echo phone( «+44 (0) 870 770 5370» ). «
» ;
echo phone( «0044 (0) 870 770 5370» ). «
» ;
echo phone( «+436764505509» ). «
» ;
echo phone( «(+38-048) 784-15-46 » ). «
» ;
echo phone( «(38-057) 706-34-03 » ). «
» ;
echo phone( «+38 (044) 244 12 01 » ). «
» ;
?>
Функция полностью решает поставленную задачу.
Из недостатков функции следует отметить отсутствие анализа медленных участков с целью оптимизаци, а также обработки телефонных номеров, где есть код города, но нет кода страны (в этом случае достаточно бить на блоки функцией phoneBlocks или воспользоваться одним из решений выше). При использовании ее в какой-либо реализации необходимо заменить глобальную переменную на ссылку в параметре, а также можно доработать или заменить формат вывода, за который отвечает функция phoneBlocks.
Самое интересное
Используя информацию с сайтов:
http://www.mtt.ru/info/def/index.wbp
http://www.hella.ru/code/codeuro.htm
http://www.scross.ru/guide/phone-global/
я собрал массив данных по всем представленным странам, включая города-исключения, флаги zeroHack, а также коды мобильных сетей. Код можно загрузить здесь.
Быстродействие
Вопреки всем самым пессимистичным ожиданиям, код отрабатывает 10.000 номеров менее чем за 2 секунды.
Подбор маски ввода по телефонному номеру
Введение
Обзор существующих решений
Предлагаемое решение
В результате было решено доработать привычную маску ввода так, чтобы она менялась в соответствии с текущим значением номера. Кроме того, по мере ввода номера предлагается отображать название определившейся страны. Данный подход, субъективно, должен решить все недостатки перечисленных выше решений.
С учётом того, что количество стран в мире относительно невелико, было принято решение составить список масок ввода для всех стран. В качестве источника использовались сведения, опубликованные на сайте международного союза электросвязи.
Сбор данной информации преподнёс немало сюрпризов. В процессе сбора сведений приходилось учитывать все возможные варианты телефонных номеров, в том числе внутри страны. Однако, ввиду большого количества обработанной вручную информации, возможно, в собранной базе остались неточности. С течением времени планируется вносить исправления в первоначальный набор.
Программная реализация
В качестве ядра маски ввода была использована реализация jquery.inputmask, о которой многократно упоминалось на Хабрахабр. Данный плагин сейчас активно развивается и, к тому же, спроектирован таким образом, что для него достаточно просто писать расширения. Однако в данной задаче написать такое расширение оказалось практически невозможно. Я не стал дорабатывать или переписывать исходный плагин под свои нужды, т.к. его автор продолжает активную работу над расширением функционала, в результате чего применение моих правок может оказаться проблематичным. Поэтому мне пришлось написать плагин-надстройку над основным ядром, который отслеживает (плюс перехватывает) внешние воздействия и производит модификацию данных. Для того, чтобы внедрить свои обработчики внешних воздействий до обработчиков основного плагина использовался плагина-библиотека jquery.bind-first.
Сортировка разрешённых масок ввода
Поиск подходящей маски ввода
При сравнении входного текста с очередной маской из отсортированного списка принимаются во внимание только значимые символы каждой маски. Если строка оказывается длиннее маски ввода, несмотря на то что все предшествующие символы прошли проверку, данная маска ввода считается неподходящей. В случае, если входному тексту удовлетворяет несколько масок ввода, то возвращается первая из них. Далее в найденной маске все значимые символы (в том числе нешаблонные) заменяются на шаблонный, который является комбинацией всех символов, разрешённых любым из шаблонных символов.
Обработка и перехват событий
Все события навешиваются в пространстве inputmask. Это позволяет избежать некорректного поведения при вызове inputmask после инициализации надстройки (т.к. ядро при инициализации снимает все ранее установленные обработчики в пространстве inputmask).
Пример использования
Формат списка масок
Список масок представляет собой JavaScript-массив объектов, предпочтительно с одинаковым набором свойств. Как минимум одно свойство, которое содержит маску ввода, должно присутствовать у всех объектов массива. Имя параметра, содержащего маску, может быть произвольным. Ниже представлен фрагмент такого массива:
Параметры подключения плагина
До подключения требуется загрузить и отсортировать список масок. Это делается выполнением следующей функции:
Для инициализации плагина нужно применить метод inputmasks к полю ввода:
array_search
(PHP 4 >= 4.0.5, PHP 5, PHP 7, PHP 8)
array_search — Осуществляет поиск данного значения в массиве и возвращает ключ первого найденного элемента в случае успешного выполнения
Описание
Список параметров
Если needle является строкой, сравнение происходит с учётом регистра.
Возвращаемые значения
Примеры
Пример #1 Пример использования array_search()
Смотрите также
User Contributed Notes 46 notes
in (PHP 5 >= 5.5.0) you don’t have to write your own function to search through a multi dimensional array
$userdb=Array
(
(0) => Array
(
(uid) => ‘100’,
(name) => ‘Sandra Shush’,
(url) => ‘urlof100’
),
(1) => Array
(
(uid) => ‘5465’,
(name) => ‘Stefanie Mcmohn’,
(pic_square) => ‘urlof100’
),
(2) => Array
(
(uid) => ‘40489’,
(name) => ‘Michael’,
(pic_square) => ‘urlof40489’
)
);
simply u can use this
$key = array_search(40489, array_column($userdb, ‘uid’));
About searcing in multi-dimentional arrays; two notes on «xfoxawy at gmail dot com»;
It perfectly searches through multi-dimentional arrays combined with array_column() (min php 5.5.0) but it may not return the values you’d expect.
Secondly, if your array is big, I would recommend you to first assign a new variable so that it wouldn’t call array_column() for each element it searches. For a better performance, you could do;
It’s what the document stated «may also return a non-Boolean value which evaluates to FALSE.»
the recursive function by tony have a small bug. it failes when a key is 0
here is the corrected version of this helpful function:
If you are using the result of array_search in a condition statement, make sure you use the === operator instead of == to test whether or not it found a match. Otherwise, searching through an array with numeric indicies will result in index 0 always getting evaluated as false/null. This nuance cost me a lot of time and sanity, so I hope this helps someone. In case you don’t know what I’m talking about, here’s an example:
for searching case insensitive better this:
About searcing in multi-dimentional arrays;
note on «xfoxawy at gmail dot com» and turabgarip at gmail dot com;
$xx = array_column($array, ‘NAME’, ‘ID’);
will produce an array like :
$xx = [
[ID_val] => NAME_val
[ID_val] => NAME_val
]
$yy = array_search(‘tesxt’, array_column($array, ‘NAME’, ‘ID’));
will output expected ID;
I was going to complain bitterly about array_search() using zero-based indexes, but then I realized I should be using in_array() instead.
The essence is this: if you really want to know the location of an element in an array, then use array_search, else if you only want to know whether that element exists, then use in_array()
Be careful when search for indexes from array_keys() if you have a mixed associative array it will return both strings and integers resulting in comparison errors
/* The above prints this, as you can see we have mixed keys
array(3) <
[0]=>
int(0)
[1]=>
string(3) «car»
[2]=>
int(1)
>
*/
hey i have a easy multidimensional array search function
hallo every body This function matches two arrays like
search an array like another or not array_match which can match
Despite PHP’s amazing assortment of array functions and juggling maneuvers, I found myself needing a way to get the FULL array key mapping to a specific value. This function does that, and returns an array of the appropriate keys to get to said (first) value occurrence.
But again, with the above solution, PHP again falls short on how to dynamically access a specific element’s value within the nested array. For that, I wrote a 2nd function to pull the value that was mapped above.
Better solution of multidimensional searching.
I needed a way to return the value of a single specific key, thus:
To expand on previous comments, here are some examples of
where using array_search within an IF statement can go
wrong when you want to use the array key thats returned.
Take the following two arrays you wish to search:
one thing to be very aware of is that array_search() will fail if the needle is a string and the array itself contains values that are mixture of numbers and strings. (or even a string that looks like a number)
The problem is that unless you specify «strict» the match is done using == and in that case any string will match a numeric value of zero which is not what you want.
also, php can lookup an index pretty darn fast. for many scenarios, it is practical to maintain multiple arrays, one in which the index of the array is the search key and the normal array that contains the data.
//very fast lookup, this beats any other kind of search
FYI, remember that strict mode is something that might save you hours.
I had an array of arrays and needed to find the key of an element by comparing actual reference.
Beware that even with strict equality (===) php will equate arrays via their elements recursively, not by a simple internal pointer check as with class objects. The === can be slow for massive arrays and also crash if they contain circular references.
This function performs reference sniffing in order to return the key for an element that is exactly a reference of needle.
A simple recursive array_search function :
I needed a function, that returns a value by specifying a keymap to the searched value in a multidimensional array and came up with this.
My function get_key_in_array() needed some improvement:
Warning, array_search() and in_array() both search for values exactly matching the value of an element, and don’t match if a value is within the value of an element. Example:
You’ll need to iterate the array with a strpos() check if you’d like to search for a value within a value of an array.
An implementation of a search function that uses a callback, to allow searching for objects of arbitrary complexity:
For instance, if you have an array of objects with an id property, you could search for the object with a specific id like this:
For a more complex example, this function takes an array of key/value pairs and returns the key for the first item in the array that has all those properties with the same values.
The final step is a function that returns the item, rather than its key, or null if no match found:
LIKE, REGEXP. Вывод данных по шаблону (маске) в MySQL
Оператор LIKE
LIKE используется для поиска записей, данные которых совпадают с заданным шаблоном.
Для создания шаблона используются два специальных символа.
Синтаксис LIKE
Шаблон LIKE | Описание |
---|---|
LIKE ‘a%’ | Значение начинается с символа «a» |
LIKE ‘%a’ | Значение заканчивается на символ «a» |
LIKE ‘%a%’ | Значение имеет символ «a» в любом месте |
LIKE ‘_a%’ | Значение имеет символ «a» на втором месте |
LIKE ‘a__’ | Значение состоит из 3 символов, первый «a» |
LIKE ‘a%d’ | Значение начинается с символа «a» и заканчивается на символ «d» |
Рассмотрим несколько примеров.
mysql> USE Bookstore;
Database changed
mysql> SELECT id, title, author, price, shelf_position FROM books;
+—-+—————————+———————+———+—————-+
| id | title | author | price | shelf_position |
+—-+—————————+———————+———+—————-+
| 1 | Дубровский (Акция) | Александр Пушкин | 230.00 | 023A12 |
| 2 | Нос (Акция) | Николай Гоголь | 255.20 | 003C05 |
| 3 | Мастер и Маргарита | Михаил Булгаков | 263.00 | 004D11 |
| 4 | Мёртвые души (Акция) | Николай Гоголь | 173.00 | 007A15 |
| 5 | Преступление и наказание | Фёдор Достоевский | 245.00 | 004E08 |
| 6 | Война и мир | Лев Толстой | 341.00 | 020F01 |
| 7 | Анна Каренина | Лев Толстой | 346.00 | 004D05 |
| 8 | Отцы и дети | Иван Тургенев | 371.00 | 001H10 |
| 9 | Собачье сердце | Михаил Булгаков | 232.00 | 006A19 |
| 10 | Бесы | Фёдор Достоевский | 212.00 | 028A03 |
+—-+—————————+———————+———+—————-+
10 rows in set (0.00 sec)
Найдем все записи с книгами, в названии которых есть слово «Акция».
mysql> SELECT id, title, author, price, shelf_position
-> FROM books
-> WHERE title LIKE ‘%Акция%’ ;
+—-+—————————+———————+———+—————-+
| id | title | author | price | shelf_position |
+—-+—————————+———————+———+—————-+
| 1 | Дубровский (Акция) | Александр Пушкин | 230.00 | 023A12 |
| 2 | Нос (Акция) | Николай Гоголь | 255.20 | 003C05 |
| 4 | Мёртвые души (Акция) | Николай Гоголь | 173.00 | 007A15 |
+—-+—————————+———————+———+—————-+
3 rows in set (0.00 sec)
mysql> SELECT id, title, author, price, shelf_position
-> FROM books
-> WHERE author NOT LIKE ‘Николай%’ ;
+—-+———————————+————————————+———+—————-+
| id | title | author | price | shelf_position |
+—-+———————————+————————————+———+—————-+
| 1 | Дубровский (Акция) | Александр Пушкин | 230.00 | 023A12 |
| 3 | Мастер и Маргарита | Михаил Булгаков | 263.00 | 004D11 |
| 5 | Преступление и наказание | Фёдор Достоевский | 245.00 | 004E08 |
| 6 | Война и мир | Лев Толстой | 341.00 | 020F01 |
| 7 | Анна Каренина | Лев Толстой | 346.00 | 004D05 |
| 8 | Отцы и дети | Иван Тургенев | 371.00 | 001H10 |
| 9 | Собачье сердце | Михаил Булгаков | 232.00 | 006A19 |
| 10 | Бесы | Фёдор Достоевский | 212.00 | 028A03 |
+—-+———————————+————————————+———+—————-+
10 rows in set (0.00 sec)
Оператор REGEXP
Синтаксис REGEXP
Ниже представлены несколько примеров использования регулярных выражений в MySQL.
Найдем все записи книг, имя автора которых начинается с букв «А» или «Л».
mysql> SELECT id, title, author, price, shelf_position
-> FROM books
-> WHERE author REGEXP ‘^(А|Л)’ ;
+—-+—————————+———————+———+—————-+
| id | title | author | price | shelf_position |
+—-+—————————+———————+———+—————-+
| 1 | Дубровский (Акция) | Александр Пушкин | 230.00 | 023A12 |
| 6 | Война и мир | Лев Толстой | 341.00 | 020F01 |
| 7 | Анна Каренина | Лев Толстой | 346.00 | 004D05 |
+—-+—————————+———————+———+—————-+
3 rows in set (0.00 sec)
Найдем все книги, в названии которых есть слово «война».
Посмотрим какие книги находятся в шкафах на 004 ряду.
mysql> SELECT id, title, author, price, shelf_position
-> FROM books
-> WHERE shelf_position REGEXP ‘^004.*’ ;
+—-+—————————+———————+———+—————-+
| id | title | author | price | shelf_position |
+—-+—————————+———————+———+—————-+
| 3 | Мастер и Маргарита | Михаил Булгаков | 263.00 | 004D11 |
| 5 | Преступление и наказание | Фёдор Достоевский | 245.00 | 004E08 |
| 7 | Анна Каренина | Лев Толстой | 346.00 | 004D05 |
+—-+—————————+———————+———+—————-+
3 rows in set (0.00 sec)
Понравилась статья? Расскажите о ней друзьям!