Метод оценки строк PHP
Надеюсь, что один из великих умов сможет помочь мне здесь.
У меня есть ситуация, когда я получаю международный номер телефона от провайдера, и мне нужно сделать поиск в базе данных и выяснить страну, регион и тип телефона, по которому звонит телефонный номер.
Например, скажите, что я получу номер телефона +393234567891. Я должен посмотреть в таблице страну, которой принадлежит этот номер телефона. так что я знаю, что '39' - Это Италия, и у меня есть это как код страны в но я должен определить, является ли номер стационарным или сотовым телефоном. Для этого мне нужно больше информации из номера телефона, поэтому "39" - это стационарный телефон, а " 393 " - мобильный телефон. Мне нужно видеть, что номер телефона содержит "393", и поэтому я знаю, что это сотовый телефон.Мой вопрос в том, как лучше всего это оценить? Будет ли это петля через каждый сегмент телефонного номера, как сначала сравнить первые два телефонных номера с базой данных, а затем первый три, потом первые четыре, пока я не вернусь с единственным результатом? Например, если я продолжу этот пример и сравню "39" для Италии с db, я вернусь с кучей результатов, потому что есть " 39 " и " 393 " и "3939" и так далее. Итак, как лучше всего использовать весь телефонный номер, чтобы получить точное соответствие для префикса телефонного номера?
Я бы подумал, что нужно просто перебрать телефонный номер и добавить цифру телефонного номера в петлю, пока я не вернусь. имея только один результат, я просто хочу убедиться, что это самый эффективный способ достичь этого.
Какие-нибудь рекомендации? Спасибо!
4 ответа:
Я предполагаю, что у вас есть таблица, подобная:
prefix (id, number)
С такими данными, как:
1, '39' 2, '393' 3, '33' 4, '331'
Вы можете получить Самое длинное совпадение с обратным, как :
SELECT id FROM prefix WHERE "393234567891" LIKE CONCAT(number, "%") ORDER BY LENGTH(number) LIMIT 1;
Я не проверял его, но если предположить, что ваш самый короткий префикс равен 2 символам, вы можете получить некоторое улучшение (это будет проверять только префиксы, начинающиеся с
39
, то есть 1% от всех префиксов, которые у вас есть):SELECT id FROM prefix WHERE "393234567891" LIKE CONCAT(number, "%") AND number LIKE "39%" ORDER BY LENGTH(number) LIMIT 1;
Тогда вы можете иметь другую таблицу с информацией, прикрепленной к этому префиксу. например:
prefixinfo (id, prefix_id, type, data)
С такими данными, как:
1, 1, 'country', 'Italy' 2, 2, 'country', 'Italy' 3, 2, 'type', 'Landline' 4, 3, 'country', 'France' 5, 4, 'country', 'France' 6, 4, 'city', 'Paris'
Если фактический номер телефона имеет фиксированный размер, вы можете удалить его. с sub_strreplace; например, числа имеют длину 8 цифр:
$code = substr_replace($number,'',-1,8);
$code теперь будет содержать только часть кода. таким образом, вы можете легко посчитать цифры и узнать, что вам нужно.
Последние 3, которые означают мобильный телефон в 393, это то же самое для каждой страны?
Идеальной ситуацией было бы иметь таблицу для стран, а затем другую таблицу со связанными префиксами
Таким образом, как только вы определили страну, вы можете ограничить остальные ваши поиски для дальнейшего ограничения, например, 393, 3939.Countries table Subsearch Table countryMatch: 39 substrMatch: 3 // for 393 countryName: "Italy" substrCountry: 39 substrMeaning: "cell" ................... substrMatch: 5 // 395 substrCountry: 39 substrMeaning: "something else"
Я считаю, что предложенный вами метод является здравым, циклически проходя через бит за битом, пока вы не найдете соответствие с помощью SQL-запросов. Так что найдите код страны, щелкнув вычеркните первые две цифры (39) и, если они найдены, запросите результаты в таблице подзаисков. С этими результатами петля через добавление их к коду страны и посмотреть, если вы получите совпадение
$subsearchArr = array("3" => "cell","5" => "something else") # from the database $match = false; $country = 39; foreach($subsearchArr as $key => $value) { # append $key to $country e.g. 393, 395 # if this is a match to the string # set match to true and do your logic } if($match == false) # no match so landline { # logic here if landline }
Я думаю, что это сработает, но я думаю, что мне нужно увидеть точную структуру данных, чтобы быть уверенным. Но да, две таблицы определенно желательно
Возможно, лучше делать сравнения в PHP с простыми циклами массива, даже если у вас есть данные в Mysql. Постройте из базы данных (и кэша) массив PHP ожидаемых кодов стран и известных уникальных префиксов внутри каждой страны, чтобы различать мобильные, стационарные телефоны, районы и т. д.
Для каждого кода страны, который у вас есть, посмотрите, начинается ли входной номер телефона с этого кода. Как только вы найдете страну, удалите код страны из телефонного номера и проверьте оставшийся номер на соответствие список известных префиксов мобильных номеров в этой стране. Если его найдут, он будет мобильным. Если его не найдут, то это стационарный телефон.
Например, в Греции код страны-30, а все мобильные телефоны начинаются с 69 после этого. Однако если вы имеете дело со странами, где префиксы мобильных номеров неотличимы от кодов регионов (например, США и Канада), вам не повезло.function checkMSISDN($msisdn) { $countries = array( 'gr' => array( 'countryPrefix' => '30', 'mobilePrefix' => '3069', 'length' => 12, ), 'it' => array( 'countryPrefix' => '39', 'mobilePrefix' => '393', 'length' => 12, ), ) ; foreach ($countries as $countryName => $countryRules) { $msisdnCurrent = $msisdn ; $countryPrefix = $countryRules['countryPrefix'] ; $fullPrefix = $countryRules['mobilePrefix'] ; //remove leading + if any if (substr($msisdnCurrent, 0, 1) == '+') { $msisdnCurrent = substr($msisdnCurrent, 1) ; } //remove leading 00 if any if (substr($msisdnCurrent, 0, 2) == '00') { $msisdnCurrent = substr($msisdnCurrent, 2) ; } $msisdnLength = strlen($msisdnCurrent) ; if ($msisdnLength != $countryRules['length']) { //sanity check, not this country continue ; } if (substr($msisdnCurrent, 0, strlen($countryPrefix)) != $countryPrefix) { //not this country continue ; } if (substr($msisdnCurrent, 0, strlen($fullPrefix)) != $fullPrefix) { //not mobile return "isLandline" ; } else { //mobile return "isMobile" ; } } return false ; }